Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.03.06;
Скачать: CL | DM;

Вниз

как узнать 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;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.025 c
1-1109014346
Jilian
2005-02-21 22:32
2005.03.06
Проблема с Image


6-1104497406
BVV
2004-12-31 15:50
2005.03.06
TIdTCPConnection.WriteStream


8-1100680884
BRemB
2004-11-17 11:41
2005.03.06
Формат файла TIF


1-1108753570
Ji
2005-02-18 22:06
2005.03.06
Магнитные бури???


6-1104163394
integerr
2004-12-27 19:03
2005.03.06
закачка на FTP файлов в потоке