Форум: "Базы";
Текущий архив: 2005.03.06;
Скачать: [xml.tar.bz2];
Внизкак узнать ID только что добавленной записе в InterBase Найти похожие ветки
← →
YK © (2005-01-31 11:26) [0]Уважаемые Мастера!
Подскажите как узнать ID (автоинкрементное через триггер)
толко что созданной записи в InterBase/
В MS-SQL я знаю, а в InterBase нет :(
P.S.
Может подскажите где найти электронный учебник
по SQL в InterBase?
← →
Sergey13 © (2005-01-31 11:29) [1]Лучше узнавать не "после", а "до того".
ibase.ru
← →
Romkin © (2005-01-31 12:07) [2]А как ты получаешь ID? В триггере?
Вот схема:
create table T (ID integer primary key);
create generator T_ID_GEN;
create trigger T_BI_GEN for T
active before insert
as
begin
if (NEW.ID is NULL) then
NEW.ID = GEN_ID(T_ID_GEN,1);
end;
Все, почти identity сделано :)
Почему почти? А если ты вставишь запись с пустым полем - оно занумеруется. А если значение в поле уже есть - оно так и вставится, генератор дергаться не будет.
Теперь остается только в приложении написать запрос
select GEN_ID(T_ID_GEN,1) from rdb$database
и получать очередной ID прямо там, и вставлять его в поле в обработчкие OnNewRecord или использовать где хочешь.
А по сути вопроса - узнать, какое значение вставил триггер: только перечитать запись.
Да, rdb$database - просто таблица с одной записью, всегда. Это не принципиально, просто IB не позволяет сделать select без from.
← →
Romkin © (2005-01-31 12:08) [3]http://ibase.ru/devinfo/generator.htm
← →
msguns © (2005-01-31 13:52) [4]>Romkin © (31.01.05 12:07) [2]
Приведенная Вами схема не дает узнать значение ID ДО вставки.
>YK © (31.01.05 11:26)
- Перед вставкой выполнить:
SELECT gen_id(<Имя генератора>,1) from rdb$Database
Возвращенный датасет содержит одну строку с одним полем, содержащим новоу значение идент-ра.
- Вставку делать с полученным значением
← →
YK © (2005-01-31 16:50) [5]Спасибо, но по-моему
следует сделать
не
select GEN_ID(T_ID_GEN,1) from rdb$database,
а select GEN_ID(T_ID_GEN,0) ...
т.к. Значение T_ID_GEN изменилось триггером.
И ещё вопрос:
В MS-SQL есть очень удобная переменная @@identyty,
а в InterBase такого нет?
← →
Sergey13 © (2005-01-31 16:52) [6]2[5] YK © (31.01.05 16:50)
Нет, ты не понял. Перечитай еще раз [2] и [4].
← →
Desdechado © (2005-01-31 16:55) [7]GEN_ID(T_ID_GEN,0) возвращает ТЕКУЩЕЕ значение генератора, но оно может быть НЕ ТВОЕ, а измененное другой транзакцией
2 msguns
почему ж не дает, очень даже дает.
Считай нужное значение генератора ДО, потом вставляй.
← →
Deniz (2005-02-01 06:52) [8]>YK © (31.01.05 16:50) [5]
>И ещё вопрос:
В MS-SQL есть очень удобная переменная @@identyty,
а в InterBase такого нет?
Нет и не надо.
Я щас какую-нибудь глупость скажу ... (с) (Гуру MSSQL поправьте)
В MSSQL нет объекта типа генератора(IB) или последовательности(Oracle), сл-но нет возможности получить уникальное значение ДО вставки записи. Используется алгоритм типа: вставил запись - запросил сгенерированное значение. Причем там есть какие-то подводные камни, когда это работает не совсем правильно.
В IB другой алгоритм: запросил новое значение - вставил с этим значением. Если значение не нужно для дальнейшего использования(массовая вставка), и в MSSQL и в IB просто не указываешь значение. В MSSQL сработает автоинкремент, а в IB триггер на условиеif (NEW.ID is NULL) then ...
.
Учись думать по другому.
← →
YK © (2005-02-01 07:02) [9]Всё-таки почему нельза использовать
GEN_ID(T_ID_GEN,0) , если я делаю это в той же транзакции?
← →
HSolo © (2005-02-01 08:49) [10]>Всё-таки почему нельза использовать
GEN_ID(T_ID_GEN,0) , если я делаю это в той же транзакции?
Т.е. Вы хотите получить текущее значение генератора, потом увеличить его на 1 и это значение записать в базу, так?
А кто увеличит значение генератора? Или он какой был, такой и останется? И что Вы тогда получите при следующем GEN_ID(T_ID_GEN,0)? И на сколько будете его увеличивать?
А если Вы работаете с базой не один? Очень возможно, что 2 пользователя одновременно получат одно и то же тек. значение генератора; дальше, думаю, понятно :)
А что касается "в той же транзакции", так генераторы работают вне контекста транзакций.
В общем, читайте:
http://ibase.ru/devinfo/generator.htm
← →
Deniz (2005-02-01 09:44) [11]http://www.sql.ru/forum/actualthread.aspx?tid=156051
← →
msguns © (2005-02-01 10:40) [12]>Desdechado © (31.01.05 16:55) [7]
>почему ж не дает, очень даже дает.
Нет. Не дает. Определение нового ИД в триггере "ДО ВСТАВКИ" позволяет при добавлении новой записи автоматически присвоить ее ид-ру (связанному с соотв.генератором) гарантированно уникальное значение, при условии, что оно не задано явно.
Но триггер ничего не возвращает ! Поэтому клиент не узнает, с каким же все-таки ИД новая запись была добавлена в таблицу.
Такой механизм приемлим, когда клиенту сразу не нужна только что добаленная запись. А если ему запись нужна СРАЗУ ? Например, при отображении датасета после вставки новой записи надо делать ее текущей. В этом случае триггер нам не поможет и надо ручками "дернуть" (под этим словом понимается увеличение счетчика и получение на клиенте нового значения) генератор, полученное значение вставить в запрос и выполнить его. В этом случае триггер отработает "вхолостую", но именно это нас и устроит. После коммита (обязательно, если чтение и запись в разных транзакциях, что классически является правильным для отображаемых датасетов) и переоткрытия НД у нас "на руках" заранее полученный ID новой записи и мы "с легким сердцем" просто
перемещаем указатель НД в содержащую этот ID записьTDataSet.Locate(Fields[0].FieldName,ID,[])
Кстати, своим следующим предложением Вы подтверждаете мои слова. Зачем же эта фраза ?
ЗЫ. Подробное объяснение, естественно, не для Вас, а для YK ©
← →
Desdechado © (2005-02-01 10:50) [13]2 msguns
Полемизировать нет смысла, мы об одном и том же разными словами говорим.
"Триггер отработает вхолостую" только в том случае, если он ничего другого, кроме заполнения первичного ключа, не делает. А вот если что-то еще делает, то совсем даже не вхолостую.
← →
msguns © (2005-02-01 11:39) [14]>Desdechado © (01.02.05 10:50) [13]
>"Триггер отработает вхолостую" только в том случае, если он ничего другого, кроме заполнения первичного ключа, не делает. А вот если что-то еще делает, то совсем даже не вхолостую.
Я говорил не о триггере вообще, а о том, что привел Romkin в [2]. Именно эта моя реплика и вызвала у Вас интерес пополемизировать ([7]).
Считаю вопрос исчерпанным. С уважением.
← →
yk © (2005-02-01 13:08) [15]>HSolo
Значение генератора у меня увеличивается в триггере
before insert
Т.е. я записываю в одну таблицу,
затем хочу(в тй же транзакции)
взять GEN_ID(T_GEN,0)
Почему должен кто-то вклиниться?
← →
Romkin © (2005-02-01 13:10) [16]msguns © (01.02.05 10:40) [12] ДАет :) Ты не дочитал. В датасете на OnNewRecord выполнить запрос select GEN_ID(T_ID_GEN,1) from rdb$database и полученное значение вставить в нужное поле. Оно и будет новым значением. А триггер не сработает.
А вот GEN_ID(T_ID_GEN,0) - нееет! Триггер работает вне контекста транзакции. И никто и никогда не гарантирует, что другая транзакция не изменила его значение :)))
← →
Romkin (2005-02-01 13:11) [17]yk © (01.02.05 13:08) [15] Закон подлости сработает уже при двух пользователях. И ты долго будешь искать глюк...
← →
Johnmen © (2005-02-01 13:13) [18]см. http://delphimaster.net/view/3-1107230737/
пост [21]
← →
msguns © (2005-02-01 13:43) [19]>Romkin © (01.02.05 13:10) [16]
Не работаю с IBDataSet и не вставляю записи "в гриде", поэтому, действительно, не обратил внимания на указанный Вами метод класса (точнее, его использование). Может, "в гриде" я и имею возможность получить новое значение генератора, запрошенное самим классом, и т.о. позиционировать датасет на новый рекорд. Однако я предпочитаю "не доверять" такие вещи кому-то, а прописывать их явно. Возможно, я и неправ, но это уже явный офтоп.
По поводу же сабжа - Johnmen © абсолютно верно отметил главное: непонимание автором принципа действия основных механизмов СУБД: триггеров, генераторов, транзакций и т.д.
На ibase.ru до неприличия обширный материал по этому поводу, однако суток автору оказалось недостаточно, чтобы просто туда заглянуть.
← →
Romkin (2005-02-01 14:06) [20]msguns © (01.02.05 13:43) [19] http://sql.ru/forum/actualthread.aspx?tid=156051&pg=-1#1288937
И что такое вставить записи "в гриде"? :)
← →
YK © (2005-02-01 15:02) [21]Переделала на
select GEN_ID(ID_Tab1_gen,1) from rdb$database into :ID_TAB1;
insert into "Tab1"("ID_Tab1",...)
values(:ID_TAB1,...);
несмотря на утверждение Romkin что триггер не
сработае, он сработал! И теперь у меня значение ID_TAB1 в TAB1
на 1 больше чем в
переменной :TAB_1
8-(
← →
msguns © (2005-02-01 15:04) [22]>Romkin (01.02.05 14:06) [20]
Это ресурс у меня стабильно не работает: говорит, что произошла ошибка сервера. ;(
>И что такое вставить записи "в гриде"? :)
Ну это ж я на известном жаргоне, шоб было понятнее. Имеется в виду, конечно же, редактируемый НД.
Подколка ? ;))
← →
msguns © (2005-02-01 15:05) [23]>YK © (01.02.05 15:02) [21]
А ну-ка быстренько текст триггера и полный текст запроса на вставку в студию !!!
;)
← →
Johnmen © (2005-02-01 15:05) [24]А где переменная TAB_1 ?
:)
← →
yk © (2005-02-01 15:14) [25]Да всё ведь банально!
Непойму в чем дело 8-(
Вот ОНО:
CREATE TRIGGER "CREATE_ID_CLIENT" FOR "Client"
ACTIVE BEFORE INSERT POSITION 0
AS BEGIN
New."ID_Client" = GEN_ID(ID_Client_gen, 1);
END
CREATE TRIGGER "CREATE_ID_CLIENT_ADDRESS" FOR "Client_Address"
ACTIVE BEFORE INSERT POSITION 0
AS BEGIN
New."ID_Client_Address" = GEN_ID(ID_Client_Address_gen, 1);
END
create procedure INSERT_ALL_FOR_CLIENT
(SurnameCUR char(20) ,NameCUR char(20),
CountryCUR char(20) )
as
declare variable ID_Adr integer;
begin
select GEN_ID(ID_CLIENT_ADDRESS_gen,1) from rdb$database
into :ID_Adr;
insert into "Client_Address"("ID_Client_Address","Country")
values(:ID_Adr,:CountryCUR);
insert into "Client"("Surname","Name","ID_CLIENT_ADDRESS")
values(:SurnameCUR,:NameCUR,:PatronymicCUR,:ID_Adr);
end!!
← →
yk © (2005-02-01 15:16) [26]Ведь триггер должен сработать!
← →
Johnmen © (2005-02-01 15:17) [27]М-дя... Случай запущенный...
Полное нежелание читать указанные факи и ответы в данной ветке :(
Хотя бы [2].
← →
yk © (2005-02-01 15:19) [28]ААААААААААААААААААААА!!!!!!!!!!!!!!!!!!!
ПонятноОООООООООО!!!!
if(New.Id)is null
!!!!!!!!!
:))))))
← →
msguns © (2005-02-01 15:20) [29]>yk © (01.02.05 15:14) [25]
Ааааааааааааааффффффффигеееееть !!!
Барышня, КТО ВАС НАУЧИЛ ТАК ПИСАТЬ ТРИГГЕРА ????????
Как говорил классик жанра Соловьев "засстрелиться" !
← →
yk © (2005-02-01 15:25) [30]Спасибо!
Я вас всех люблю!
p.s.
Это мой первый... триггер
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2005.03.06;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.046 c