Форум: "Базы";
Текущий архив: 2002.11.21;
Скачать: [xml.tar.bz2];
ВнизКак правильно организовать транзакцию на вставку в IB? Найти похожие ветки
← →
KIR (2002-10-31 01:01) [0]Народ, ситуация следующая (для примера упростим содержание таблиц): Имеется таблица, содержащая PK по полю ID и, скажем, номер документа. Имеются еще несколько таблиц в которых определенное количество записей ссылаются на главную таблицу (в таблицах имеется поле, скажем MasterID). Записи туда добавляются автоматически при запуске некой процедуры (некоторые рассчитываются, некоторые беруться из StringGrid"ов). Так вот суть этой процедуры такова: добавить 1 запись в главную таблицу (ID генерится с помощью генератор+транзакция "перед вставкой"), затем заполняются все подчиненные таблицы, в которых в поле MasterID заносится только что сгенеренный ID из главной таблицы?
Вопрос следующий: как грамотно организовывается такая вставка:
1. С помощью ХП и огромной кучи параметров (в общей сложности полей около 30)?
2. С помощью Query ---"---?
3. С помощью StartTransaction-Commit из кода клиента?
4. Еще как-то?
Спасибо!
← →
KIR (2002-10-31 01:01) [1]Да, добавление: использую IB 6.5 и FIBPlus
← →
KIR (2002-10-31 10:12) [2]Народ, оч. надо!!!
← →
Max Zyuzin (2002-10-31 10:16) [3]http://delphi.mastak.ru/cgi-bin/forum.pl?look=1&id=1035978375&n=1
А вообще с помощью транзакции и рамках транзакции уже запросы на добавления делай
← →
Desdechado (2002-10-31 10:40) [4]starttran и commit обязательно.
а между ними как хочешь - один или несколько квери и/или ХП.
← →
KIR (2002-10-31 10:55) [5]Если сделать так:
MyDataBase.StartTransaction
MasterTable.Append;
MasterTable["FrstFied"] := "test";
MasterTable.Post;
DetaiTable1.Append;
DetailTable1["MasterID"] := MasterTable["ID"];
DetailTable1.Post;
DetaiTable2.Append;
DetailTable2["MasterID"] := MasterTable["ID"];
DetailTable2.Post;
MyDataBase.Commit;
ругается. В хелпе к FIBPlus вычитал, что это все делается через DataBase.DefaultTransaction
The following procedure illustrates how to start and commit transaction in response to a button click:
procedure TForm1.ApplyButtonClick(Sender: TObject);
end;
begin
pFIBDatabase1.Open;
pFIBTransaction1.StartTransaction;
pFIBDataSet1.Insert;
pFIBDataSet1.FieldByName("QUANTITY").AsInteger := StrToInt(Edit1.Text);
pFIBDataSet1.Post;
pFIBTransaction1.Commit;
In the preceding example, you could substitute Rollback for Commit.
← →
Max Zyuzin (2002-10-31 11:00) [6]>KIR © (31.10.02 10:55)
Я так понял вы пользуетесь компонентами IBTable?
← →
Desdechado (2002-10-31 11:02) [7]1. табличный подход и ИБ - как отверткой гвозди забивать
2. перед вставкой во 2-ю таблицу считать ID из мастера
← →
Ops (2002-10-31 11:20) [8]0. Запускай транзакцию (явно)
1. Получи ID - хранимой процедурой. (Чтобы другие незахватили)
2. Все табицы открывай через квери
3. Сделай всем квери кеширование
4. Работай с ними как хочешь
5. Конец работы
а) сохраняй кеширование
б) применяй транзакцию
← →
KIR (2002-10-31 11:27) [9]>Max Zyuzin Я пользуюсь компонентами библиотеки FIBPlus и соответственно pFIBDataSet
>Ops А как ЯВНО запустить транзакцию в pFIBDataDase, используя свойство DefaultTransaction? Я это спрашиваю, так, как если написать просто
pFIBDataBase1.StartTransaction;
...
...
pFIBDataBase1.Commit
Ввдается ошибка: "Format "%s" ivalid or incompatible with argument"
← →
KIR (2002-10-31 12:44) [10]>Ops Получи ID - хранимой процедурой. (Чтобы другие незахватили)
А как это правильно сделать?
← →
KIR (2002-10-31 13:59) [11]В итоге я сделал так:
procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
begin
TA1.StartTransaction;
try
MasterDS.Append;
MasterDS.Post;
i := MasterDS["ID"];
DetailDS.Append;
DetailDS["MasterID"] := i;
DetailDS.Post;
TA1.Commit;
except
TA1.Rollback;
raise;
end;
end;
Правильно? Или все-таки надо вязаться с ХП?
← →
KIR (2002-11-01 02:10) [12]Народ, ау...
← →
Max Zyuzin (2002-11-01 09:03) [13]Если у тебя все работает, то правильно :)
← →
KIR (2002-11-01 11:03) [14]Работать-то работает. У меня! А щас как поставишь на 10 машин и начнется... поэтому я так сильно и интересуюсь
← →
Johnmen (2002-11-01 11:28) [15]>KIR © (31.10.02 13:59)
Приведенный код совершенно ничего не говорит об уникальности ID в мастере ! Так что приведи, как он формируется у тебя...
← →
KIR (2002-11-01 12:07) [16]> Johnmen кусок моего первого сообщения в этой ветке: ... ID генерится с помощью генератор+транзакция "перед вставкой"),...
Вроде, насколько я понимаю смысл работы tFIBTransaction, все должно работать нормально. Единственное, что меня смущает совет Ops по поводу получения ID хранимой процедурой. Надо ли это? Что это длжна быть за процедура? Как из нее получать ID? С помошью Query? Не слишком ли это большое нагромождение одного на другое?
← →
Johnmen (2002-11-01 12:28) [17]>KIR © (01.11.02 12:07)
Генерится то он генерится, а как твоим приложением получатся ?
Варианты : 1. Запросом 2. ХП 3. Никак не получается (устанавливается в триггером)
← →
KIR (2002-11-01 12:33) [18]Никак не получается - устанавливается триггером.
P.S. Сам щас прочитал - бред. Прошу большого прощения! Конечно в первом сообщении надо было написать "генератор+триггер "перед вставкой".
← →
Johnmen (2002-11-01 12:48) [19]Понятно...
Наиболее корректное решение - сначала получить ID (ХП, запрос), а потом это значение вставить (из триггера убрать).
Это относится к Мастеру, если у него предполагается Детейл.
← →
KIR (2002-11-01 13:02) [20]То есть в ХП вызвать генератор, потом полученное значение вернуть через SELECT * FROM ХП, затем использовать полученное значение внутри транзакции, внутри которой выполняяется вставка сначала в Мастер а затем в подчиненные таблицы?
← →
Johnmen (2002-11-01 13:12) [21]>KIR © (01.11.02 13:02)
>То есть в ХП вызвать генератор...
Да.
>...потом полученное значение вернуть через SELECT * FROM ХП...
Зачем так сложно ? Просто компонент StoredProc
>...затем использовать полученное значение внутри транзакции...
Тр-ия здесь непричем...
>внутри которой выполняяется вставка сначала в Мастер а затем в
>подчиненные таблицы?
Да.
← →
Ops (2002-11-01 14:16) [22]Если ты создавал уникальное поле то должен был
1) Сделать генератор
2) Сделать тригер (на вставку)
IF (NEW.ID_PRODUCTTYPE IS NULL) THEN
NEW.ID_PRODUCTTYPE = GEN_ID(GEN_PRODUCTTYPE_ID,1);
3) СДЕЛАТЬ ХРАНИМУЮ ПРОЦЕДУРУ
ID = GEN_ID(GEN_PRODUCTTYPE_ID, 1);
Использование хран процедуры
DM.IBSP_GenID.ExecProc;
ID := DM.IBSP_GenID.ParamByName("ID");
Но Я думаю ты уже во всем разобрался :-)
← →
Johnmen (2002-11-01 14:34) [23]>Ops (01.11.02 14:16)
>2) Сделать тригер (на вставку)
> IF (NEW.ID_PRODUCTTYPE IS NULL) THEN> NEW.ID_PRODUCTTYPE = GEN_ID(GEN_PRODUCTTYPE_ID,1);
На тему этого IF уже были обсуждения.
Позвольте привести свое мнение - он НЕ нужен ! Резоны :
Его наличие предполагает, что разрабатываемое приложение вдруг начнет писать, не указывая ID ! Но приложение ваше или нет ? Или вы настолько неуверены в том, что написали ?
Далее. Если вдруг ID будет не NULL, а вполне конкретное непримлемое значение ? И что ? Вы защитились от этого ?
Так что вот.........
← →
Alexandr (2002-11-01 14:43) [24]2Johnmen: Не читая всего флейма, позволю себе не согласиться с последним утверждением. Есть несколько причин, когда if сильно облегчит жизнь, а апохого от него ничего нет для первичного ключа.
← →
Ops (2002-11-01 14:50) [25]>Johnmen
В целом согласен.
← →
Johnmen (2002-11-01 15:20) [26]>Alexandr © (01.11.02 14:43)
>...а апохого от него ничего нет для первичного ключа.
Согласен, нет плохого, и хорошего тоже, то есть это как гриб свинушка, и пользы нет и вреда никакого...
>Есть несколько причин, когда if сильно облегчит жизнь...
Приведи хотя бы одну. Мне это интересно !
:)
← →
Alexandr (2002-11-01 15:26) [27]1) копирование таблиц с сохранением ссылочной целостности.
Скажем, есть справочник, на который ссылаются другие таблицы, и мы хотим создать еще одну такую же таблицу в этой или другой (репликация?) базе данных. Если в исходной таблице есть пропуски в значениях ПК, что совершенно нормально, то значения ПК для одних и тех же записей в этих таблицах будут разными, а это конец.
2) Приложение перед вставкой записи в справочник может "застолбыть себе значение ПК (генератора) сделав
select gen_id (code,1) from rdb$database. А потом зная его, его уже и вставить в таблицу, и зная его после вставки точно знать какую имеено запись вставили. Очень просто и быстро.
ну хотябы это.
← →
Johnmen (2002-11-01 16:09) [28]>Alexandr © (01.11.02 15:26)
Честно говоря, я не совсем понял, как приведенные доводы влияют на применение вышеуказанного IF. Особенно п.2) А судя по 1) так этот IF и приведет к "это конец" :o)))
← →
Johnmen (2002-11-01 23:12) [29]>Alexandr © (01.11.02 15:26)
По п.1) ты прав, я - тормознул...:-))) Дествительно, это возможное применение. Хотя такие вещи если делаются, то наверняка единично или крайне редко, а в этом случае триггер можно просто отключить.
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2002.11.21;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.007 c