Tomsk Sysadmins Forum
Windows => Программирование => Topic started by: Дмитрий Жданов on April 06, 2007, 21:13:23
-
Есть две таблицы - Patient и Osmotr. Таблица Osmotr связанна с таблицей Patient Внешним ключом по полю Pat_ID. В табл. Пациент оно является первичным ключом, значения в это поле вносятся с помощью генератора...........
Нужно, чтобы при занесении пациента в Patient (Pat_ID) автоматически это же значение заносилось в поле Pat_ID таблицы Osmotr. Здесь это поле не является первичным ключом........На нем просто установленно значение Not Null.
Я эти таблицы соединил с помощью внешнего ключа, но желаемого эффекта не получил..............В тупик такой зашел.......В литературе найти ничего не могу......Там просто пишется, что после создания внешнего ключа все значения родительской таблицы будут автоматом присваиваться дочерней (тому же полю, что и в родительской)....Может надо что то в самом приложении настраивать, чтобы значения автоматом полю присваивались?? Приложение, кстати, в Delphi разрабатывается............
Внешний ключ в скрипте после создания всех таблиц прописывал:
ALTER TABLE Osmotr
ADD CONSTRAINT Pat_OSmotr FOREIGN KEY(Pat_ID) REFERENCES
Patient(Pat_ID)
On Delete Cascade
On Update Cascade;
Подскажите, что нужно сделать?? Буду вам очень признателен.....................
-
Там просто пишется, что после создания внешнего ключа все значения родительской таблицы будут автоматом присваиваться дочерней (тому же полю, что и в родительской)....
Невнимательно, видимо, читали. Вот и заблудились.
В вашем же скрипте написано:On Delete Cascade
On Update Cascade;
что означает реакцию СУБД при удалении и обновлении, но никак ни при добавлении записей.
Вариант 1: Примитивный.
Сразу после добавления записи в таблицу Patient выполнить запросSELECT MAX(Pat_ID) AS LastPatID FROM Patient
далее значение LastPatID использовать для вставки записей в дочернюю таблицу.
Вариант 2: Чуть более продвинутый.
Использовать хранимую процедуру (с именем, например, GetPatIDGen) вместо запроса.
CREATE GENERATOR PatIDGen;
SET GENERATOR PatIDGen TO 0;
SET TERM ^;
CREATE TRIGGER PatientBeforeInsert FOR Patient
ACTIVE BEFORE INSERT
AS
BEGIN
NEW.Pat_ID = GEN_ID(PatIDGen, 1);
END ^
CREATE PROCEDURE GetPatIDGen
RETURNS (CurrentPatID INTEGER)
AS
BEGIN
CurrentPatID = GEN_ID(PatIDGen, 0);
END ^
SET TERM; ^
Без соответствующей доработки оба варианта исключают одновременную работу нескольких пользователей с таблицами. Сами подумайте почему...
-
Спасибо большое Мне и не нужна одновременная работа нескольких пользователей с таблицей.....Максимум один человек будет БД использовать............Работа нескольких пользователей с базой в ооочень далёкой перспективе Рабочее место одного врача-специалиста будет.........О полной автоматизации больнички ещё даже и речи не велось)
Вариант 1: Примитивный.
Сразу после добавления записи в таблицу Patient выполнить запросSELECT MAX(Pat_ID) AS LastPatID FROM Patient
далее значение LastPatID использовать для вставки записей в дочернюю таблицу.
Т. е. здесь, если правильно понял, потом надо будет написать запрос на вставку значения LastPatID в дочернюю таблицу???
Генераторы я сделал.......все отлично работает......Только здесь ступор какой то
-
Т. е. здесь, если правильно понял, потом надо будет написать запрос на вставку значения LastPatID в дочернюю таблицу???
Да. К примеру:SourceQuery.SQL.Clear;
SourceQuery.SQL.Append('SELECT MAX(Pat_ID) AS LastPatID');
SourceQuery.SQL.Append('FROM Patient');
...
LastPatID := SourceQuery.FieldByName('LastPatID').AsInteger;
...
YourQuery.SQL.Clear;
YourQuery.SQL.Append('INSERT INTO Osmotr (..., Pat_ID, ...)');
YourQuery.SQL.Append('VALUES (..., :Pat_ID, ...)');
YourQuery.ParamByName('Pat_ID').AsInteger := LastPatID;
....
SourceQuery.SQL.Clear;
SourceQuery.SQL.Append('SELECT MAX(Pat_ID) AS LastPatID');
SourceQuery.SQL.Append('FROM Patient');
...
LastPatID := SourceQuery.FieldByName('LastPatID').AsInteger;
...
YourQuery.SQL.Clear;
YourQuery.SQL.Append('INSERT INTO Osmotr (..., Pat_ID, ...)');
YourQuery.SQL.Append('VALUES (..., ' + IntToStr(LastPatID) + ', ...)');
...
YourQuery.SQL.Clear;
YourQuery.SQL.Append('INSERT INTO Osmotr (..., Pat_ID, ...)');
YourQuery.SQL.Append('SELECT CAST(... AS ...), ..., MAX(Pat_ID), CAST(... AS ...), ...)');
YourQuery.SQL.Append('FROM Patient');
...
-
Спасибо)) Но он почему то в этом месте ошибку выдает:
...
LastPatID := SourceQuery.FieldByName('LastPatID').AsInteger;
...
"SourseQuery:Field 'LastPatID' not found"
-
Догадался как убрать ошибку.........Но поля все равно не заполняются
Почему то переменной LastPatId значение не присваивается........Сам запрос правильно выполняется
-
Почему то переменной LastPatId значение не присваивается...
Исходники в студию! Телепаты в отпуске...
-
Modul.SourseQuery.SQL.Clear;
Modul.SourseQuery.SQL.Append('SELECT MAX(Pat_ID) AS LastPatID');
Modul.SourseQuery.SQL.Append('FROM Patient');
LastPatID:=Modul.SourseQuery.FieldByName('LastPatID').AsInteger;
Modul.IBOsmotr.SQL.Clear;
Modul.IBOsmotr.SQL.Append('Insert into Osmotr (Pat_ID,Date_ID,Doc_ID,Zhaloby,CHDD,CHSS,Weight,Height,Recom)');
Modul.IBOsmotr.SQL.Append('Values (:Pat_ID,:Date_ID,:Doc_ID,:Zhaloby,:CHDD,:CHSS,:Weight,:Height,:Recom)');
Modul.IBOsmotr.ParamByName('Pat_ID').AsInteger:=LastPatID;
Вот.........Переменной LAstPatID значение не присваивается в строчке:
LastPatID:=Modul.SourseQuery.FieldByName('LastPatID').AsInteger;
Поэтому значение и не заносится. Нуль постоянно считывает. До неё все рабочее. В IBConsole проверил...правильно считает.
-
Modul.SourseQuery.SQL.Clear;
Modul.SourseQuery.SQL.Append('SELECT MAX(Pat_ID) AS LastPatID');
Modul.SourseQuery.SQL.Append('FROM Patient');
LastPatID:=Modul.SourseQuery.FieldByName('LastPatID').AsInteger;
Modul.IBOsmotr.SQL.Clear;
Modul.IBOsmotr.SQL.Append('Insert into Osmotr (Pat_ID,Date_ID,Doc_ID,Zhaloby,CHDD,CHSS,Weight,Height,Recom)');
Modul.IBOsmotr.SQL.Append('Values (:Pat_ID,:Date_ID,:Doc_ID,:Zhaloby,:CHDD,:CHSS,:Weight,:Height,:Recom)');
Modul.IBOsmotr.ParamByName('Pat_ID').AsInteger:=LastPatID;
Вот.........Переменной LAstPatID значение не присваивается в строчке:
LastPatID:=Modul.SourseQuery.FieldByName('LastPatID').AsInteger;
Поэтому значение и не заносится. Нуль постоянно считывает. До неё все рабочее. В IBConsole проверил...правильно считает.
Ну так, а Modul.SourseQuery.Open кто будет делать после Modul.SourseQuery.SQL.Append('FROM Patient') ?
А после Modul.IBOsmotr.ParamByName нужен Modul.IBOsmotr.ExecSQL
И на мой взгляд, все это очень не правильно и не аккуратно.
-
А как правильней написать??)
-
Я просто раньше на BDE только все делал........Здесь разобраться никак не могу
-
Я просто раньше на BDE только все делал........Здесь разобраться никак не могу
BDE это всего лишь Borland Database Engine набор драйверов для работы с БД причем разными.
Обсуждать недостатки не будем, скажу лишь, что если Вы используете компоненты которые "напрямую" работают с gds.dll (или как она там называется) никакой разницы нет.
Я не понимаю зачем "в ручную" делать insert'ы в базу.
Кроме того, какой смысл городить клиент-серверное приложение, если Вы сразу же архитектурно ограничиваетесь работой одного пользователя, если Вам понадобится работа двух пользователей переделать будет очень сложно.
На мой взгляд проще использовать TDB компоненты для заполнения полей записи и использовать транзакции для того чтобы пользователь мог откатить случайно внесенные изменения.
-
Я совсем о другому сделал..............
Завел переменную(PatID), которой присвоил порядковый номер пациента (Pat_ID).
номер соответствует выбранной записи в таблице Patient:
PatID:= Modul.DatPat.FieldByName('Pat_ID').AsInteger;
Затем для занесения в таблицу Osmotr в поле Pat_ID просто присвоил эту переменную определенной строке в таблице.Это осуществляется при вставке новой записи.
-
А не проще ли всё это через DataSet организовать? Или я чего-то не догоняю?
-
Я так и сделал...............Там проблема с генераторами тоже была...............Надо было у ключевого столбика (В котором значение генератора сохраняется) свойство Requared (неправильно написал по моему в значение FAlse перевести)
Я так и сделал...............Там проблема с генераторами тоже была...............Надо было у ключевого столбика (В котором значение генератора сохраняется) свойство Requared (неправильно написал по моему в значение FAlse перевести)
А запись только так получилось сделать.......................Даже если ссылочную целостность в скрипте при создании БД прописывать (по идее все новые значения из родительского столбца одной таблицы должны записываться в дочерние столбцы других таблиц)
-
Я так и сделал...............Там проблема с генераторами тоже была...............Надо было у ключевого столбика (В котором значение генератора сохраняется) свойство Requared (неправильно написал по моему в значение FAlse перевести)
Не понял что там цитировалось но...
Вообще-то этот самый так называемый столбик ставится Required в False когда значение генератора будет изменяться с помощью (допустим триггеров) базы, но я бы посоветовал DataSet подключить к генератору, что бы он мог обращаться к генератору и получать из него значение до вставки в базу. Тогда можно и нужно свойство Required этого поля поставить в True.
PS. Я кстати тоже базу для больницы делаю.
-
Не понял что там цитировалось но...
Вообще-то этот самый так называемый столбик ставится Required в False когда значение генератора будет изменяться с помощью (допустим триггеров) базы, но я бы посоветовал DataSet подключить к генератору, что бы он мог обращаться к генератору и получать из него значение до вставки в базу. Тогда можно и нужно свойство Required этого поля поставить в True.
PS. Я кстати тоже базу для больницы делаю.
Я триггеры как раз и использую) Сначала генератор к нему создаю, потом триггер для него, чтобы значения из него брать.......
Не работало просто с этим свойством ничего..............Хоть убей) Пока не отрубишь - программа ругаеттся......Хочешь - потестируй программку........Начальную её версию)
http://freelance.tomsk.ru/up.php?id=3241 (http://freelance.tomsk.ru/up.php?id=3241)
А для какой больницы??)
-
А для какой больницы??)
Секрет
У меня база сетевая, таблиц около 40 включая справочные.
Я триггерами сначала начал делать обработку инфы, а потом понял что если интерфейс на Дельфи делать, то проще в Дельфи это и реализовать. Поэтому триггера все поотключал нафиг, даже которые генераторы переключают.
Ты же через DataSet делал я полагаю!? или SQL везде писал? Как я тут заметил.
Ты анализы (допустим биохимию) к истории цеплял или к пациенту?
Кстати о меню, у тебя там не очень удобно сделано когда сверху меню выбираешь, что бы оно разворачивалось, а то так мне кажется не для всех привычно. Либо я думаю их на кнопки вынести, либо в какие нибудь группы запихать, лишь бы меню разворачивалось.
Ещё где МРТ когда Чекбоксы ставишь, пустые он у тебя не берёт, может так и надо. Хотя это же бэта версия
PS. Понравилась цветовая гамма где анализы, возможно украду
-
Секрет
У меня база сетевая, таблиц около 40 включая справочные.
Я триггерами сначала начал делать обработку инфы, а потом понял что если интерфейс на Дельфи делать, то проще в Дельфи это и реализовать. Поэтому триггера все поотключал нафиг, даже которые генераторы переключают.
Ты же через DataSet делал я полагаю!? или SQL везде писал? Как я тут заметил.
Ты анализы (допустим биохимию) к истории цеплял или к пациенту?
Кстати о меню, у тебя там не очень удобно сделано когда сверху меню выбираешь, что бы оно разворачивалось, а то так мне кажется не для всех привычно. Либо я думаю их на кнопки вынести, либо в какие нибудь группы запихать, лишь бы меню разворачивалось.
Ещё где МРТ когда Чекбоксы ставишь, пустые он у тебя не берёт, может так и надо. Хотя это же бэта версия
PS. Понравилась цветовая гамма где анализы, возможно украду
Сохранение\удаление\изменение и вставка через DataSet прорабатываются..............Только процедуру при нажатии кнопки нужную вызвать надо. Сортировка пациентов, поиск - на SQL написаны.........Для каждого анализа своя таблица.......Там по сути каждое окошко соответствует таблице......Кроме небольших (течение болезни. например). Так проще, чем все данные в одну таблицу запихивать.
Поначалу всё кнопками было - потом придрались к этому и вверх вынести пришлось......Мне они тоже больше нравятся....А то, что Чебоксары пустые Так и задумано........Если пустые, то они заполнены - полные - галочка в них появляется) Вот так
А плагиатом нехорошо заниматься
-
Т.е. процедуры у тебя в интербэйзе храняться, а из Дельфи ты их вызываешь?
А у меня всё в Дэльфи обрабатывается, там возможностей больше, поэтому и решил там их делать. Твой вариант наверное шустрее должен работать, хотя думаю разницы почти нет.
-
Т.е. процедуры у тебя в интербэйзе храняться, а из Дельфи ты их вызываешь?
А у меня всё в Дэльфи обрабатывается, там возможностей больше, поэтому и решил там их делать. Твой вариант наверное шустрее должен работать, хотя думаю разницы почти нет.
Нет процедуры в Dаta Set хранятся. Их автоматически сгенерировать можно......А потом, при нажатии кнопки например, происходит их вызов.
Для примера:
with Modul do begin
DatPat.Insert;
end;
И не надо париться полностью весь SQL код прописывать на кнопке. Процедура в DataSet постоянно хранится)
Ты не в Областной детской больнице БД делаешь??
-
Нет процедуры в Dаta Set хранятся. Их автоматически сгенерировать можно......А потом, при нажатии кнопки например, происходит их вызов.
Для примера:
with Modul do begin
DatPat.Insert;
end;
И не надо париться полностью весь SQL код прописывать на кнопке. Процедура в DataSet постоянно хранится)
Ты не в Областной детской больнице БД делаешь??
Нет
Ты имеешь в виду свойство DataSet.InsertSQL или DataSet.UpdateSQL что ли? А так я ХЗ где там процедуры хранятся!? Если это - то я так и делаю, собственно для этого ДатаСет в основном и нужен!
Кстати фильтр пробовал через свойство Filter делать?
-
Нет
Ты имеешь в виду свойство DataSet.InsertSQL или DataSet.UpdateSQL что ли? А так я ХЗ где там процедуры хранятся!? Если это - то я так и делаю, собственно для этого ДатаСет в основном и нужен!
Кстати фильтр пробовал через свойство Filter делать?
Нет)
Я через DataSet Editor автоматически эти свойства генерирую (содержание их).
А зачем тебе фильтр нужен??
Ты не знаешь как сделать, чтобы картинки в базе сохранялись??? А то ругается Delphi что то
-
Ты не знаешь как сделать, чтобы картинки в базе сохранялись??? А то ругается Delphi что то
Не пробовал, в понедельник попробую отпишусь. Знаю что для этого BLOB поля нужно использовать в базе.
-
Вот тебе процедурка, при нажатии на кнопку рисунок сохраняется в базу из внешнего файла. Из книги достал, сам бы не догадался Фишка в том, что нужно использовать потоки класса TStream, и обязательно перевод Таблицы в режим Edit! Если чё сам не пробовал, но думаю здесь всё верно.
procedure TMainForm.OpenBClick(Sender: ТОbjесt);
var S: TStream;
FileS: TFileStream;
begin
if not OpenD.Execute then exit;
pFIBDataSet1.Edit;
S := pFIBDataSet1.CreateBlobStream(pFIBDataSet1.FieldByName('GRAPHIC') , bmReadWrite);
try
FileS := TFiIeStream.Create(OpenD.FileName, fmOpenRead);
S.CopyFrom(FileS, FileS.Size);
finally
FileS.Free;
S.Free;
pFIBDataSet1.Post;
end;
end;
-
Вот тебе процедурка, при нажатии на кнопку рисунок сохраняется в базу из внешнего файла. Из книги достал, сам бы не догадался Фишка в том, что нужно использовать потоки класса TStream, и обязательно перевод Таблицы в режим Edit! Если чё сам не пробовал, но думаю здесь всё верно.
procedure TMainForm.OpenBClick(Sender: ТОbjесt);
var S: TStream;
FileS: TFileStream;
begin
if not OpenD.Execute then exit;
pFIBDataSet1.Edit;
S := pFIBDataSet1.CreateBlobStream(pFIBDataSet1.FieldByName('GRAPHIC') , bmReadWrite);
try
FileS := TFiIeStream.Create(OpenD.FileName, fmOpenRead);
S.CopyFrom(FileS, FileS.Size);
finally
FileS.Free;
S.Free;
pFIBDataSet1.Post;
end;
end;
Спасибо Только он на FileS := TFiIeStream.Create(OpenPictureDialog1.FileName, fmOpenRead);
ругается....пишет, что TStream - неизвестный идентификатор. Библиотеку похоже подключить надо какую то) Не подскажешь как книжка называется??
-
Не подскажешь как книжка называется??
Мир InterBase.
Ковязин А. Н., Востриков С. М.
У меня она в электронном виде.
-
Мир InterBase.
Ковязин А. Н., Востриков С. М.
У меня она в электронном виде.
Спасиба...у меня она есть) А библиотека какая не в курсе???
-
Спасиба...у меня она есть) А библиотека какая не в курсе???
нет