Форум: "Базы";
Текущий архив: 2003.09.18;
Скачать: [xml.tar.bz2];
ВнизВставка записей в таблицу InterBase Найти похожие ветки
← →
asd (2003-08-27 18:55) [0]Привет! Подскажите пожалуйста как можно узнать при вставке ID записи, который присвоил генератор InterBase?
← →
Calm (2003-08-27 19:00) [1]select max(id) from YourTable
Если же нужно одиним махом, то можно делать добавление через хранимую процедуру.
В ХП сделать один выходной параметр, который получать так:
NewID=gen_id(YourGenerator, 0); // текущее значение генератора
← →
HSolo (2003-08-27 19:02) [2]Вариант 1: перед вставкой записи взять очередное значение генератора, и вставлять с уже известным значением.
Вариант 2: написать хранимую процедуру, к-рая вставляет запись и возвращает соотв.значение
Все прочее - от лукавого :)
← →
HSolo (2003-08-27 19:03) [3]> select max(id) from YourTable
Вот так делать не надо. Можно сильно нарваться при интенсивной многопользовательской работе
← →
Pat (2003-08-27 23:58) [4]>который присвоил генератор InterBase
Генератор ничего никому не присваивает
Вставлять значения на клиенте. IBX и FIBPlus поддерживают работу с генераторами для "autoinc" полей.
З.Ы. "autoinc" в кавычках :-)
← →
asd (2003-08-28 07:53) [5]>Вариант 1: перед вставкой записи взять очередное значение генератора, и вставлять с уже известным значением
Скажите а как можно из программы вызвать это значение? (Хотя оно уже может измениться)
Опишу ситуацию. Происходит вставка записи и надо чтобы указатель в Gride стоял на вставленной записи. Но дело в том что частенько это не последняя запись (много народу работает).
Или подскажите пожалуйста пример хранимой процедуры, которая бы делала вставку и как получить от нее значение newid.
Заранее благодарен
← →
Zacho (2003-08-28 08:01) [6]
> asd (28.08.03 07:53) [5]
Если используешь IBX - то у TIBDataSet и TIBQuery есть св-во GeneratorField.
А в общем случае - в событии OnNewRecord выполнять запрос типа SELECT GEN_ID(MY_GEN,1) FROM RDB$DATABASE и полученное значение присваивать полю.
← →
Жук (2003-08-28 08:27) [7]
> asd (28.08.03 07:53) [5]
> Опишу ситуацию. Происходит вставка записи и надо чтобы указатель
> в Gride стоял на вставленной записи.
Append
← →
HSolo (2003-08-28 10:37) [8]CREATE PROCEDURE INS_UPD_BAZA(
ID INTEGER,
FNAME VARCHAR(100),
FDATER DATE)
RETURNS (
IDENT INTEGER)
AS
BEGIN
if (id>0) then
begin
ident = id;
update baza set
fname = :fname, fdater = :fdater
where ident = :id;
end
else begin
ident = gen_id(g_baza, 1);
insert into baza(ident, fname, fdater)
values (:ident, :fname, :fdater);
end
suspend;
END
← →
Zacho (2003-08-28 10:40) [9]
> HSolo © (28.08.03 10:37) [8]
Можно, конечно, но толку-то от этого в IBX ? Только лишний гемморой.
← →
AlexWeb (2003-08-28 12:13) [10]> Zacho © (28.08.03 08:01) [6]
А в общем случае - в событии OnNewRecord выполнять запрос типа SELECT GEN_ID(MY_GEN,1) FROM RDB$DATABASE и полученное значение присваивать полю.
Нефига не выйдет. Т.к. "GEN_ID(MY_GEN,1)" увеличит значение генератора "MY_GEN" на "1".
← →
HSolo (2003-08-28 12:15) [11]1) Человек просил пример процедуры, что мне, жалко? :)
2) От ТАКОГО в точности - и впрямь лишний этот самый. Ну а если вставлять надо не в одну таблицу? У меня вообще-то в 4 штуки вставка идет, это просто кусок выдран для упрощения понимания :)
3) Я пользуюсь FIBPlus. В данном случае это важно?
← →
HSolo (2003-08-28 12:18) [12]> "GEN_ID(MY_GEN,1)" увеличит значение генератора "MY_GEN" на "1".
Правильно. И при следующей вставке Вы получите СЛЕДУЮЩЕЕ значение генератора. Или не Вы, а другой пользователь. Тем самым гарантируется уникальность ID Ваших записей. На то и генератор :)
А Вам что нужно? Чтобы каждый раз возвращалось одно и то же? Ну, тогда GEN_ID(MY_GEN,0) - только зачем? Что Вы с этим делать будете?
← →
AlexWeb (2003-08-28 13:05) [13]HSolo © (28.08.03 12:18) [12]
Если событии "OnNewRecord" Вы сначала вызовите:
1. "SELECT GEN_ID(MY_GEN,1) FROM RDB$DATABASE";
2. а потом вставите запись с этим значение ген.
То это все неправильно. Вы два раза увеличиваете знач. ген.
Пример: в п.1 вы получили значение ген. MY_GEN=100 и присвоили его полю, а в п.2 при "коммите" сервер сам сгенерирует значение MY_GEN=101 и присвоит его полю. Чё не так, а?
← →
Zacho (2003-08-28 13:11) [14]
> HSolo © (28.08.03 12:15) [11]
Согласен :)
> AlexWeb (28.08.03 13:05) [13]
> HSolo © (28.08.03 12:18) [12]
>
> То это все неправильно. Вы два раза увеличиваете знач. ген.
> Пример: в п.1 вы получили значение ген. MY_GEN=100 и присвоили
> его полю, а в п.2 при "коммите" сервер сам сгенерирует значение
> MY_GEN=101 и присвоит его полю. Чё не так, а?
Вот как раз так - правильно. Сервер "сам" ничего не генерирует и не вставляет, тем более при коммите, просто триггера надо проавильно писать. Советую посмотреть http://www.ibase.ru/devinfo/generator.htm
← →
AlexWeb (2003-08-28 13:25) [15]> Zacho © (28.08.03 13:11) [14]
Сервер "сам" ничего не генерирует и не вставляет, тем более при коммите, просто триггера надо проавильно писать. Советую посмотреть http://www.ibase.ru/devinfo/generator.htm
А кто говорил, что "сервер вставляет", читайте внимательней "присвоит его полю". А насчет "Сервер "сам" ничего не генерирует", а кто генерирует, "Бабангидум" что ли? Триггер наверное срабатывает на сервере, а ни на клиенте!!!
← →
HSolo (2003-08-28 13:30) [16]Уфф...
Если Вам нужно значение ID на клиенте - то см.Zacho © (28.08.03 08:01) [6] - и не утруждайте зря триггер, ничего никому там присваивать не надо! Клиент уже все присвоил, зачем второй раз-то?
Или есть опасения, что клиент все-таки не присвоит? Тогда в триггере:
if (new.id is null) then new.id = GEN_ID(MY_GEN,1);
← →
Zacho (2003-08-28 13:34) [17]
> AlexWeb (28.08.03 13:25) [15]
Так я же сказал : "триггера надо правильно писать".
Например, так:
CREATE TRIGGER MY_TABLE_BI0 FOR AMORT_GROUPS
ACTIVE BEFORE INSERT POSITION 0
AS
begin
if (new.ID is NULL) then new.ID=GEN_ID(MY_GEN,1);
end
← →
AlexWeb (2003-08-28 13:35) [18]Смотрите реальный пример:
procedure TForm1.IBQuery1NewRecord(DataSet: TDataSet);
var
i: integer;
begin
IBQuery_Temp.SQL.Text:= "SELECT GEN_ID(GEN_QL_CI_ID,0) FROM RDB$DATABASE";
IBQuery_Temp.Open;
i:= IBQuery_Temp.Fields [0].asinteger;
IBQuery_Temp.Close;
IBQuery1.FieldByName ("CI_ID").asinteger:= i+1;
end;
Или Вы не согласны? ;-)
> Zacho © (28.08.03 13:11) [14]
А это как "просто триггера надо проавильно писать"? Чё, там много надо писать что ли?
← →
Zacho (2003-08-28 13:41) [19]
> AlexWeb (28.08.03 13:35) [18]
Категорически не согласен с таким примером ! Очень большая вероятность нарушения ПК при многопользовательской работе.
Правильно - так:
procedure TForm1.IBQuery1NewRecord(DataSet: TDataSet);
var
i: integer;
begin
IBQuery_Temp.SQL.Text:= "SELECT GEN_ID(GEN_QL_CI_ID, 1) FROM RDB$DATABASE";
IBQuery_Temp.Open;
i:= IBQuery_Temp.Fields [0].asinteger;
IBQuery_Temp.Close;
IBQuery1.FieldByName ("CI_ID").asinteger:= i;
end;
Только я бы для запроса вместо TIBQuery использовал TIBSQL.
← →
AlexWeb (2003-08-28 13:49) [20]Да ты пример пробовал свой, что пытаешься доказать мне?
procedure TForm1.IBQuery1NewRecord(DataSet: TDataSet);
var
i: integer;
begin
IBQuery_Temp.SQL.Text:= "SELECT GEN_ID(GEN_QL_CI_ID,1) FROM RDB$DATABASE";
IBQuery_Temp.Open;
i:= IBQuery_Temp.Fields [0].asinteger;
IBQuery_Temp.Close;
IBQuery1.FieldByName ("CI_ID").asinteger:= i;
end;
Сначало думай (проверь код на выполнение), а потом говори!!!
← →
Zacho (2003-08-28 13:56) [21]
> AlexWeb (28.08.03 13:49) [20]
Привести тебе пример из рабочего (причем давно и успешно работающего) проекта ? Вот:
procedure TfmSprav.ibdsSpravNewRecord(DataSet: TDataSet);
begin
sqlID.ExecQuery;
ibdsSprav.FieldByName("ID_OS").Value:=sqlID.FieldByName("ID").Value;
sqlID.Close;
end;
А вот запрос в sqlID.SQL - SELECT GEN_ID(GEN_OS,1) FROM RDB$DATABASE
← →
Жук (2003-08-28 13:59) [22]Об чём спор-то ? У Zacho © абсолютно рабочий код. Единственное, что не могу понять, зачем этот гемор с генератором, если есть TIBDataSet ?
← →
Zacho (2003-08-28 14:02) [23]
> Жук © (28.08.03 13:59) [22]
Во-во. И св-во GeneratorField :)
← →
HSolo (2003-08-28 14:10) [24]> AlexWeb (28.08.03 13:49) [20]
Да Zacho-то свой пример пробовал, не сомневайтесь. А вот пробовали ли Вы, что получится из Вашего AlexWeb (28.08.03 13:35) [18] если 2 пользователя попытаются одновременно вставить запись? Могу по шагам расписать, даже не пробуя :))
← →
AlexWeb (2003-08-28 14:12) [25]> Жук © (28.08.03 13:59) [22]
Как будто я свой код не проверял!
"Жук ©" Тогда покажи, где ошибка в моем коде?
← →
AlexWeb (2003-08-28 14:14) [26]> HSolo © (28.08.03 14:10) [24]
Могу по шагам расписать
Давай!
← →
Zacho (2003-08-28 14:19) [27]2 AlexWeb:
Еще раз настоятельно рекомендую прочитать http://www.ibase.ru/devinfo/generator.htm
← →
NickBat (2003-08-28 14:20) [28]to AlexWeb:
Текущее значение генератора 735.
Первый пользователь получил 735 и второй 735
Оба на клиенте сделали приращение на 1.
В итоге два пользователя пытаются записать ID=736
Дальше расписывать?
← →
AlexWeb (2003-08-28 15:08) [29]Когда я использую Ваш пример то в результате получается:
- при выполнении запроса, ID = 735;
- при присвоении 735 полю и выполнении CommitRetaining условие в триггер IF срабатывает (значит оно = NULL)и генератор инкрементирует. Соотв., данному полю присваивается 736.
В чем сдесь проблема?
← →
AlexWeb (2003-08-28 15:11) [30]Нашел в чем проблема!
В IBUpdateSQL.InsertSQL-е
insert into QL_CI
(NAME_FULL)
values
(:NAME_FULL)
небыло АвтоИнка в InsertSQL-е:
insert into QL_CI
(CI_ID, NAME_FULL)
values
(:CI_ID, :NAME_FULL)
Все работает!
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2003.09.18;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.009 c