Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 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.037 c
1-1109098758
Knoxville
2005-02-22 21:59
2005.03.06
Как закодировать данные?


1-1109093174
Alexois
2005-02-22 20:26
2005.03.06
Помогите пожалуйста


3-1107795797
Vantage-10
2005-02-07 20:03
2005.03.06
Врменная таблийа в Access


1-1109060871
Maks Realov
2005-02-22 11:27
2005.03.06
Как лучше реализовать запись множества дин. данный в файл?


1-1109075955
Nad89
2005-02-22 15:39
2005.03.06
Кликнуть по ссылке в TWebBrowser





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский