Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Базы данных и репортинг > Получить ID добавленой записи


Автор: ArtemRubtsov 20.11.2007, 22:55
БД MS SQL 
компонент ADOQuery
Есть задача добавить запись в таблицу БД, при этом для нее будет сгенерировано некое уникальное значение счетчика
Вопрос как получить значение этого счетчика для добаваляемой записи, чтобы потом эту запись можно было найти по этому уникальному ID?

так не работает, выдает ошибку в строке 5, пишет что поле ID не найдено
Код

DBQuery.Close;
DBQuery.SQL.Add('INSERT INTO TABLE1 (FIELD1,FIELD2) VALUES(:Param2,:Param3)');
DBQuery.SQL.Add('SELECT * from TABLE1 where ID=:Param1');
DBQuery.Parameters.ParseSQL(frmMain.DBQuery.SQL.Text,true);
DBQuery.Parameters.ParamByName('Param1').Value:= frmMain.DBQuery.FieldValues['ID']; 
DBQuery.Parameters.ParamByName('Param2').Value:= Filed1Value;
DBQuery.Parameters.ParamByName('Param3').Value:=Filed2Value;  
DBQuery.ExecSQL;
Result := DBSource.DataSet.FieldByName('ID').AsInteger;

Автор: Deniz 21.11.2007, 07:27
Примерно так
Код

declare @ID int;
insert into ... values( ... );
set @ID = @@identity;
select ... from ... where id=@ID;

Автор: pseud 21.11.2007, 11:31
не знаю как в MS SQL, но в Oracle есть Sequencies

попробуем без всяких примочек, как если бы мы работали с Paradox

Код

DBQuery.Active := False;
DBQuery.SQL.Clear;
DBQuery.SQL.Add('INSERT INTO TABLE1 (FIELD1,FIELD2) VALUES(:Param2,:Param3)');
DBQuery.Parameters.ParamByName('Param2').Value:= Filed1Value;
DBQuery.Parameters.ParamByName('Param3').Value:=Filed2Value; 
DBQuery.ExecSQL;

DBQuery.Active := False;
DBQuery.SQL.Clear;
DBQuery.SQL.Add('SELECT MAX(ID) as max_id from TABLE1');
DBQuery.Active := True;
id := DBQuery.FieldByName('max_id').AsInteger;

DBQuery.Active := False;
DBQuery.SQL.Clear;
DBQuery.SQL.Add('SELECT * from TABLE1 WHERE ID = ' + IntToStr(id));
DBQuery.Active := True;



хотя мой совет - использовать процедуру, в которой:
1. сделать инсерт
2. вернуть ID

а то ведь первый ExecSQL мог и не выполниться

Добавлено через 55 секунд
имеется ввиду процедуру SQL сервера

Автор: Akella 21.11.2007, 15:31
а если между 
Код

DBQuery.Active := False;
DBQuery.SQL.Clear;
DBQuery.SQL.Add('INSERT INTO TABLE1 (FIELD1,FIELD2) VALUES(:Param2,:Param3)');
DBQuery.Parameters.ParamByName('Param2').Value:= Filed1Value;
DBQuery.Parameters.ParamByName('Param3').Value:=Filed2Value; 
DBQuery.ExecSQL;


и

Код

DBQuery.Active := False;
DBQuery.SQL.Clear;
DBQuery.SQL.Add('SELECT MAX(ID) as max_id from TABLE1');
DBQuery.Active := True;
id := DBQuery.FieldByName('max_id').AsInteger;


Произойдёт:
1. Исключение
2. добавление новой записи другим клиентом

Автор: pseud 21.11.2007, 17:44
Akella, поэтому я и написал:
Цитата(pseud @  21.11.2007,  11:31 Найти цитируемый пост)
хотя мой совет - использовать процедуру

которая после инсерта вернет ID 

Автор: ArtemRubtsov 21.11.2007, 20:45
Цитата(Deniz @ 21.11.2007,  07:27)
Примерно так
Код

declare @ID int;
insert into ... values( ... );
set @ID = @@identity;
select ... from ... where id=@ID;

спасибо
я попробую так

Автор: Deniz 22.11.2007, 07:45
ArtemRubtsov, попробуй мой код весь запихать в ADOQuery и выполнить Open

Автор: SergXPI 22.11.2007, 17:28
Я использую следующий прием.
При вставке новой записи в любое поле типа String пишу 'новая запись' (можно написать все что угодно).
Суть в том, что по этой записи ты сможеш всегда идентифицировать новую запись и определить ее ID
Код

 Table.Insert;
 Table.FieldByName('Param1').AsString:='новая запись';
 Table.Post;
 IF Table.select('Param1','новая запись',[loCaseInsensitive]) Then
  Begin
   ID:=Table.FieldByName('max_id').AsInteger;
   Table.FieldByName('Param1').AsString:='';
  End; 


для БД MS SQL  суть таже, нужно только синтаксис поменять

Автор: Deniz 23.11.2007, 06:56
SergXPI, нельзя так делать, если кто-то в тот же момент добавит - будет 2, 3, 4 и т.д. новых записей.
Вариант может пройти только если есть возможность прямо управлять транзакциями с определенным уровнем изоляции и коммитеть только после выборки ID.
Вместо 'новая запись' на клиенте можно 1 раз сгенерировать GUID и ставить уже его.

Автор: SergXPI 23.11.2007, 11:41
Если пользователей несколько, тогда
Код

 Table.Insert;
 Table.FieldByName('Param1').AsString:='новая запись для '+IntToStr(N);
 Table.Post;
 IF Table.select('Param1','новая запись для '+IntToStr(N),[loCaseInsensitive]) Then
 ...


где, N - уникальный номер пользователя

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)