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

Вниз

Вставка записей в таблицу 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;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.021 c
6-58825
and_2
2003-07-15 08:44
2003.09.18
ping!


14-58871
Kost
2003-08-29 20:16
2003.09.18
StringGird


3-58542
Mikle
2003-08-28 10:01
2003.09.18
Проблема с Query в Delhi4


1-58779
Юлия
2003-09-05 13:47
2003.09.18
Работа с excel


1-58618
Jacob
2003-09-04 21:56
2003.09.18
Ms Outlook