Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 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
14-100063
panov
2001-12-11 15:37
2002.01.31
Угадайте, очем речь?


1-99931
starik
2002-01-12 22:40
2002.01.31
Уменьшить размер пикселя


4-100113
vic_774N
2001-12-03 14:47
2002.01.31
Delphi IDE - а попробуйте-ка послать текст в редактор !!!


1-99989
SkyR
2002-01-14 01:53
2002.01.31
Работа с указателями...


1-99970
Юлик
2002-01-14 15:13
2002.01.31
Формат даты





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