delphi dxExpress MySQL: неверное значение LAST_INSERT_ID

Я разрабатываю приложение в Delphi и хочу вставить записи в таблицу Mysql. Затем я хочу узнать значение идентификатора вставленной записи. Поэтому я пишу следующий код.
Во время выполнения выполняется вставка и добавляется запись, но возвращаемое значение для идентификатора равно нулю!! в чем моя ошибка?!!

-- MySql  table create
CREATE TABLE Sample_Table (
  id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  mobile_number varchar(20) DEFAULT NULL,
  message_body text,
 PRIMARY KEY (id)
);

--- Delphi code

SQLCon := TSQLConnection.Create(self);
  with SQLCon do begin
   Close;
   DriverName := 'MySQL';
   GetDriverFunc := 'getSQLDriverMYSQL';
   LibraryName := 'dbxmys.dll';
   VendorLib := 'LIBMYSQL.dll';
   LoginPrompt := false;
   Params.Values['HostName'] := '127.0.0.1';
   Params.Values['Database'] := 'sms_test';
   Params.Values['User_Name'] := 'root';
   Params.Values['Password'] := 'root';
   Open;
end;

SQLQry := TSQLQuery.Create(self);
with SQLQry do begin
  Close;
  SQLConnection := SQLCon;

  SQL.Clear;
  SQL.Add('INSERT INTO Sample_Table ');
  SQL.Add('(mobile_number, message_body) VALUES');
  SQL.Add(format('(%s, %s);',[QuotedStr('989121011689'), QuotedStr('Text1')]));
  ExecSQL();
  Close;

  SQL.Clear;
  SQL.Add('SELECT LAST_INSERT_ID() EngineRefNo;');
  Open;
  First;
  ListBox1.items.Add(FieldByName('EngineRefNo').AsString);
  Close;
end;

SQLCon.Close;

любой совет?


person Moh Tarvirdi    schedule 05.12.2012    source источник


Ответы (2)


Вы должны получить идентификатор за один раз

SQLQry := TSQLQuery.Create(self);
with SQLQry do begin
  SQLConnection := SQLCon;

  SQL.Add('INSERT INTO Sample_Table ');
  SQL.Add('(mobile_number, message_body) VALUES');
  SQL.Add(format('(%s, %s);',[QuotedStr('989121011689'), QuotedStr('Text1')]));

  SQL.Add('SELECT LAST_INSERT_ID() EngineRefNo;');

  Open;
  ListBox1.items.Add(FieldByName('EngineRefNo').AsString);
  Close;
end;

SQLCon.Close;

и вы должны подумать об использовании параметров для предотвращения инъекции sql

SQLQry := TSQLQuery.Create(self);
with SQLQry do begin
  SQLConnection := SQLCon;

  SQL.Add('INSERT INTO Sample_Table ');
  SQL.Add('( mobile_number, message_body ) VALUES');
  SQL.Add('( :mobile_number, :message_body );');

  SQL.Add('SELECT LAST_INSERT_ID() EngineRefNo;');

  ParamByName( 'mobile_number' ).Value := '989121011689';
  ParamByName( 'message_body' ).Value := 'Text1';

  Open;
  ListBox1.items.Add(FieldByName('EngineRefNo').AsString);
  Close;
end;

SQLCon.Close;
person Sir Rufo    schedule 05.12.2012
comment
@MohTarvirdi что за ошибка? Компиляция или выполнение из SQL? Пожалуйста, приведите все сообщение об ошибке. Что вы тестировали? С параметром или без? - person Sir Rufo; 07.12.2012
comment
Я пробовал оба подхода выше, используя C++ Builder XE3, но безуспешно. См. stackoverflow.com/questions/39906572/< /а>. - person Totte Karlsson; 07.10.2016

По-видимому, это проблема известный с delphi .

цитируя приведенную выше ссылку:

В некоторых приложениях ODBC (включая Delphi и Access) могут возникать проблемы с получением значения автоинкремента в предыдущих примерах. В этом случае попробуйте следующее утверждение в качестве альтернативы:

SELECT * FROM tbl WHERE auto IS NULL;

Этот альтернативный метод требует, чтобы для переменной sql_auto_is_null не было установлено значение 0. См. Системные переменные сервера.

Итак, в вашем случае (непроверенный):

SQLCon := TSQLConnection.Create(self);
  with SQLCon do begin
   Close;
   DriverName := 'MySQL';
   GetDriverFunc := 'getSQLDriverMYSQL';
   LibraryName := 'dbxmys.dll';
   VendorLib := 'LIBMYSQL.dll';
   LoginPrompt := false;
   Params.Values['HostName'] := '127.0.0.1';
   Params.Values['Database'] := 'sms_test';
   Params.Values['User_Name'] := 'root';
   Params.Values['Password'] := 'root';
   Open;
end;
SQLQry := TSQLQuery.Create(self);
with SQLQry do begin
  Close;
  SQLConnection := SQLCon;

  SQL.Clear;
  SQL.Add('INSERT INTO Sample_Table ');
  SQL.Add('(mobile_number, message_body) VALUES');
  SQL.Add(format('(%s, %s);',[QuotedStr('989121011689'), QuotedStr('Text1')]));
  ExecSQL();
  Close;

  SQL.Clear;
  SQL.Add('SELECT id FROM Sample_Table WHERE id IS NULL');
  Open;
  First;
  ListBox1.items.Add(FieldByName('Id').AsString);
  Close;
end;

SQLCon.Close;
person whosrdaddy    schedule 05.12.2012
comment
Я протестировал приведенный выше код и вернул ноль (и, естественно, должен вернуть ноль, как указано выше). теперь, как я могу получить идентификатор последней вставленной записи? - person Moh Tarvirdi; 07.12.2012
comment
@MohTarvirdi: вы должны установить для флага sql_auto_is_null значение 1. Дополнительную информацию см. здесь: dev.mysql.com/doc/refman/5.5/en/ - person whosrdaddy; 07.12.2012