Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 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);
begin
pFIBDatabase1.Open;
pFIBTransaction1.StartTransaction;
pFIBDataSet1.Insert;
pFIBDataSet1.FieldByName("QUANTITY").AsInteger := StrToInt(Edit1.Text);
pFIBDataSet1.Post;
pFIBTransaction1.Commit;
end;

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.01 c
1-69269
VJar
2002-11-11 22:36
2002.11.21
Связь кнопок формы м кнопками клавиатуры


1-69368
AndreyAG
2002-11-10 09:51
2002.11.21
Окна


1-69328
DVM
2002-11-12 14:39
2002.11.21
Прозрачные надписи у значков в ListView.


1-69393
Strumpf
2002-11-09 23:34
2002.11.21
Как изменить высоту элемента TMenuItem?


14-69559
Akhmadey
2002-11-03 19:19
2002.11.21
Где взять рабочие компоненты





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский