Форум: "Базы";
Текущий архив: 2002.01.31;
Скачать: [xml.tar.bz2];
ВнизКак возвратить значение сгенерированного ID на клиента Найти похожие ветки
← →
Наташа (2001-12-27 09:00) [0]Суть моей проблемы:
При занесении данных в таблицу
with IBQuery1 do
SQL.clear;
SQL.add("insert into nakl(postav_id,...) values(1,...)");
ExecSQL;
end;
IBTransaction1.Active:=true;
генерируется значение nakl_id таблицы nakl на сервере.
Я не могу получить это значение на клиенте, чтобы использовать его в дальнейшем. Вернее могу, конечно, сделав select по уникальному набору полей в этой таблице, но я думаю, что это явно не оптимальный вариант.
Может посоветуете что-нибудь?
Спасибо за внимание и понимание :)
← →
Deniz (2001-12-27 09:38) [1]Хранимая процедура на сервере, возвращающая ID.
Пример:
Create procedure GetNextID
returns (ID integer) as
begin
ID = Gen_ID(GeneratorName, 1);
Suspend;
end;
Suspend вроде не обязательно (у меня в проэктах нет, но почему-то многие пишут).
Далее немного изменить код.
IBStoredProc1.StoredProcName:="GetNextID";
IBStoredProc1.Prepare;
IBStoredProc1.ExecProc;
i:=IBStoredProc1.ParamByName("ID").AsInteger;
with IBQuery1 do
SQL.clear;
SQL.add("insert into nakl(postav_id,...) values(:ID,...)");
Prepare;
ParamByName("ID").asInteger:=i;
ExecSQL;
end;
← →
Наташа (2001-12-27 09:42) [2]> Deniz
Спасибо огромное!
С меня пиво :)
← →
Deniz (2001-12-27 10:10) [3]Там поправочка в коде
← →
Deniz (2001-12-27 10:11) [4]Там поправочка в коде
with IBQuery1 do begin
пропустил.
ЗЫ:А на счет пива - это правильно, и главное приятно.
← →
Наташа (2001-12-27 10:25) [5]Всё работает, но получается, что приращение nakl_id идёт с шагом 2, а не 1, что естественно - сначала в ХП я добавляю значение генератора, а после вставки записи в таблицу генератор отрабатывает ещё один раз.
IBStoredProc1.StoredProcName:="GetNextIDNAKL";
IBStoredProc1.Prepare;
IBStoredProc1.ExecProc;
NomNakl:=IBStoredProc1.ParamByName("ID").AsInteger;
with IBQuery2 do
begin
active:=false;
SQL.clear;
SQL.Add("insert into nakl(nakl_id,textnakl,postav_id,sklad_id,firm_id)");
SQL.Add(" values(:ID,...)");
Prepare;
ParamByName("ID").asInteger:=NomNakl;
ExecSQL;
end;
Как бы всё таки сделать так, чтобы накладные шли по порядку, т.е. получать значение ID после вставки записи?
← →
GreySerg (2001-12-27 10:39) [6]убери из базы триггер на вставку, где у тебя генерится значение или измени его (если там не только генерация значения)
← →
SArthur (2001-12-27 10:41) [7]Можно, к примеру, выполнять вставку записи хранимой процедурой, которая возвращает dataset из одной записи и одного поля - ID.
Работаю в Sybase (ASA 6.0.3).
Обычно я даю вставку (ID автоинкрементное), а потом выбираю полученый ID вторым запросом. В некритичных местах - ничего страшного. А вот в критичных местах - пишу маленькую процедурку, которая вставляет запись и дает этот самый SELECT перед возвратом.
← →
Slava (2001-12-27 10:58) [8]В триггере лучше написать примерно следующее:
IF (NEW.ID IS NULL) THEN
NEW.ID = GEN_ID(GEN_ID,1);
← →
GreySerg (2001-12-27 11:08) [9]>Slava
Ну и как же таким способом на клиенте получить значение, чтобы использовать его в дальнейшем
По-моему вариант Deniz"а с хранимой процедурой - самый оптимальный
← →
prosof (2001-12-27 11:26) [10]Так можно в хранимой процедуре не
ID = Gen_ID(GeneratorName, 1);
делать а написать
ID = Gen_ID(GeneratorName, 0);
Генератор то добавляет то чего его попросят.
← →
Slava (2001-12-27 11:47) [11]> GreySerg
Это касается "убери триггер на вставку"
Не надо убирать триггер, а то вдруг кто-нибудь захочет добавить запись не из твоей программы!
А хранимая процедура - само собой.
А еще с клиента можно сделать запрос
select GEN_ID(GeneratorName, 1) from RDB$DATABASE
← →
Наташа (2001-12-27 11:58) [12]Да, насчёт убрать триггер - это не серьёзно.
Сделала вставку записи в ХП.
> prosof Слушай, гениально! Так и сделаю.
> Slava Мой триггер выглядит именно так.
А select GEN_ID(GeneratorName, 1) from RDB$DATABASE
я так поняла выдаёт из системной таблицы существующее последнее
значение генератора? Побегу пробовать. Всем БОЛЬШОЕ СПАСИБО!!!
Кстати,прочитала на ib.demo.ru
"некоторые решения с применением ХП". Там такой код
record_no=gen_id(NATUR_gen, 1);
INSERT INTO NATUR (NATUR_CODE, PERSON_CODE_E) VALUES (:record_no,:masterkey);
Но он тоже прибавляет с шагом 2 или я чего-то не поняла.
← →
Romkin (2001-12-27 12:03) [13]Значит, кто-то еще обращается к генератору
вариант Наташа (27.12.01 10:25) + Slava © (27.12.01 10:58)
самый оптимальный,
процедура же:
returns(ID integer)
begin
ID = Gen_ID(Natur_GEN,1);
end
← →
Slava (2001-12-27 12:05) [14]http://ib.demo.ru/DevInfo/generator.htm
← →
Наташа (2001-12-27 12:42) [15]Ура!Ура!Ура!
Получилось!Получилось!
← →
Deniz (2001-12-27 17:46) [16]>SArthur (27.12.01 10:41)
Вопрос о вставке в хранимой процедуре интересный но ... есть несколько случаев когда это не хорошо.
Например программа с кешированием может избежать сл. проблем:
1.После вставки, необходимо сделать в программе Query.Close ... Query.Open, чтобы получить вставленную/редактированную запись.
2.Commit или Rollback делается на все таблицы в транзакции, следовательно нельзя для одной таблицы Commit а для другой Rollback.
Можно еще написать (ударение на последнюю а), но каждый для себя сам решает эти проблемы. Я сначала делал именно так (insert/edit/delete) в хранимых процедурах, но отказался.
← →
SArthur (2001-12-28 10:41) [17]Обычно я так и делаю.
В смысле: вставка, запрос на ID, обновление грида (п.1 твоего письма). Такие оперции вполне можно использовать в режимах редактирования справочников. Там идет транзакция по одной, двум, редко - трем таблицам.
Там, где нужно вставить в несколько связанных таблиц, а где-нибуть что-либо апдейтнуть... Не-е-е... Там только хранимой процедурой. Во-первых, уменьшается сетевой траффик. Во вторых, эта самая процедура делает все и, в результате, ID тебе уже и не нужен. В третьих, программный код более читабельный:
var tq: TQuery;
Begin
...
tq:=TQuery.Create(nil);
try
tq.DatabaseName:="myDB_alias";
tq.SQL.Add("CALL MyBigInsert_Update_Proc(:prm1, :prm2)");
tq.ParamByName("prm1").AsInteger:=1;
tq.ParamByName("prm2").AsString :="text";
DataModule1.Database1.StartTransaction;
try
tq.ExecSQL; // или tq.Open, ежели есть результат
DataModule1.Database1.Commit;
except
On E: Exception do begin
DataModule1.Database1.Rollback;
// <error handler code>
end;
end;
finally
tq.Free;
end;
...
End;
Примерно так. И с BDE и с ADO работает.
Реализация MyBigInsert_Update_Proc напрямую зависит от используемого DB сервера.
Ну, это, поругайте код, что ли... :-)))
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2002.01.31;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.005 c