LAST_INSERT_ID() возвращает ноль

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

SeVer
незнакомец
Сообщения: 8
Зарегистрирован: 26.06.2007 16:06:38
Откуда: Чистополь
Контактная информация:

LAST_INSERT_ID() возвращает ноль

Сообщение SeVer »

Сабж.

Код: Выделить всё

      DM.SQLQuery.SQL.Clear;
      DM.SQLQuery.SQL.Add('INSERT INTO provresult (dt, num, T, P, result, provopID, stendID, mode)');
      DM.SQLQuery.SQL.Add('VALUES (Now(), :num, :T, :P, :result, :provopID, :stendID, :workmode)');
      DM.SQLQuery.Params.ParamByName('num').AsInteger:= DevNum;     // todo разобраться с количеством параметров
      DM.SQLQuery.Params.ParamByName('T').AsFloat:= Temper;
      DM.SQLQuery.Params.ParamByName('P').AsInteger:= P;
      DM.SQLQuery.Params.ParamByName('result').AsBoolean:= PassRes;
      DM.SQLQuery.Params.ParamByName('provopID').AsInteger:= 0;  // todo Подставить
      DM.SQLQuery.Params.ParamByName('stendID').AsInteger:= 0;  // todo Подставить
      DM.SQLQuery.Params.ParamByName('workmode').AsInteger:= WorkMode;
      DM.SQLQuery.ExecSQL;
     
      DM.SQLQuery.SQL.Clear;
      DM.SQLQuery.SQL.Add('SELECT LAST_INSERT_ID() FROM provresult');
      DM.SQLQuery.Open;
      ResID:= DM.SQLQuery.Fields[0].AsInteger;  //всегда = 0 :-(
      DM.SQLQuery.Close;


Кто-нибудь сталкивался?
Аватара пользователя
Attid
долгожитель
Сообщения: 2588
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E
Контактная информация:

Сообщение Attid »

а что такое LAST_INSERT_ID ??
SeVer
незнакомец
Сообщения: 8
Зарегистрирован: 26.06.2007 16:06:38
Откуда: Чистополь
Контактная информация:

Сообщение SeVer »

Attid писал(а):а что такое LAST_INSERT_ID ??

Это функция MySQL сервера, которая возвращает последнее в данной сессии значение автоинкрементного поля после выполнения INSERT.
Аватара пользователя
Attid
долгожитель
Сообщения: 2588
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E
Контактная информация:

Сообщение Attid »

а вот теперь раскажи мне где в первом посте хоть слово про MySQL?
если не сможешь я удалю всю ветку. и тебя еще забаню за несоблюдение правил по информативности поста.

ЗЫ. никогда не юзал MySQL и не кому не советую использовать кроме как в ВЕБ проэктах.
ЗЫЫ. думаю ошибка в sql синтаксисе.
SeVer
незнакомец
Сообщения: 8
Зарегистрирован: 26.06.2007 16:06:38
Откуда: Чистополь
Контактная информация:

Сообщение SeVer »

Attid писал(а):а вот теперь раскажи мне где в первом посте хоть слово про MySQL?

Если кто-то эту функцию использовал, он и так догадается. Если не использовал - вряд ли сможет помочь.
Attid писал(а):если не сможешь я удалю всю ветку. и тебя еще забаню за несоблюдение правил по информативности поста.

Да ради бога. Только не нервничай так.

Attid писал(а):ЗЫ. никогда не юзал MySQL и не кому не советую использовать кроме как в ВЕБ проэктах.

Твое дело. Но я сюда не за этим советом пришел.

Attid писал(а):ЗЫЫ. думаю ошибка в sql синтаксисе.

Та же самая функция в MySQL-Front возвращает то, что надо.
Проблема в том, что и INSERT и LAST_INSERT_ID должны быть вызваны в одной сессии. Похоже, что каждый вызов ExecSQL и Open - это разные сессии.
Аватара пользователя
debi12345
долгожитель
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение debi12345 »

а что такое LAST_INSERT_ID ??

Значение ключевого поля в момент добавления записи, нужно для для авто-конструирования SQL-команды INSERT (в случае, если Вы не сами эту команду пишете, а доверяете датасету ). Все нормальные сервера БД (PostgreSQL, FireBird, SQLite3,... ) предоставляют этот интерфейс, без него невозможно автоматическое сохранение записей, добавленых к гридам.
В MSEgui+SQlite3, чтобы эта схема работала - в таблице обязательно должно быть поле с атрибутом "PRIMARY KEY" ( MSEgui ищет это поле в определении таблицы - иначе не за что зацепиться ). Может, у Вас похожий случай, и у вас остутствует такое поле ?

Проблема в том, что и INSERT и LAST_INSERT_ID должны быть вызваны в одной сессии. Похоже, что каждый вызов ExecSQL и Open - это разные сессии.

Он валидный не после SQL-команды "INSERT", а после вызова "dataset.Append" - что совсем не одно и то же.
SeVer
незнакомец
Сообщения: 8
Зарегистрирован: 26.06.2007 16:06:38
Откуда: Чистополь
Контактная информация:

Сообщение SeVer »

Значение ключевого поля в момент добавления записи, нужно для для авто-конструирования SQL-команды INSERT (в случае, если Вы не сами эту команду пишете, а доверяете датасету ).

Кусок кода приведен выше. Команда написана ручками.
Все нормальные сервера БД (PostgreSQL, FireBird, SQLite3,... ) предоставляют этот интерфейс, без него невозможно автоматическое сохранение записей, добавленых к гридам.

А причем тут гриды?
В MSEgui+SQlite3, чтобы эта схема работала - в таблице обязательно должно быть поле с атрибутом "PRIMARY KEY" ( MSEgui ищет это поле в определении таблицы - иначе не за что зацепиться ). Может, у Вас похожий случай, и у вас остутствует такое поле ?

CREATE TABLE `provresult` (
`id` bigint(20) unsigned NOT NULL auto_increment,
`dt` datetime NOT NULL default '0000-00-00 00:00:00',
`num` int(9) unsigned NOT NULL default '0',
`T` float NOT NULL default '0',
`P` smallint(2) unsigned NOT NULL default '0',
`result` smallint(1) unsigned NOT NULL default '0',
`provopID` bigint(11) unsigned NOT NULL default '0',
`stendID` bigint(11) unsigned NOT NULL default '0',
`mode` smallint(1) unsigned NOT NULL default '0' COMMENT '0 - проверка, 1 - поверка',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=cp1251;

Он валидный не после SQL-команды "INSERT", а после вызова "dataset.Append" - что совсем не одно и то же.

LAST_INSERT_ID([expr])
Returns the last automatically generated value that was inserted into an AUTO_INCREMENT column. See section 24.1.3.126 mysql_insert_id().
mysql> select LAST_INSERT_ID();
-> 195
А уж каким образом его вставили - через SQL команду INSERT или через вызов метода Append - не важно.
Аватара пользователя
debi12345
долгожитель
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение debi12345 »

А причем тут гриды?


Позволяет после фиксации новых записей командой "dataset.applyupdate[s]" не потерять позиции в гриде и не записать в чужие строки.

Я смотрю, вы работаете по старинке - то есть через низкоуровневый SQL. И это в 21-м веке. Почему так ? Только в этм примере ?
SeVer
незнакомец
Сообщения: 8
Зарегистрирован: 26.06.2007 16:06:38
Откуда: Чистополь
Контактная информация:

Сообщение SeVer »

debi12345 писал(а):
Позволяет после фиксации новых записей командой "dataset.applyupdate[s]" не потерять позиции в гриде и не записать в чужие строки.

Хм. Что-то я мысль не уловлю. У меня вообще нет гридов. Мне данные не надо отображать, только записать в базу, а получаю я их от внешнего девайса. Генератор отчётов у меня в другом месте. Или я под гридами что-то не то понимаю?
debi12345 писал(а):Я смотрю, вы работаете по старинке - то есть через низкоуровневый SQL. И это в 21-м веке. Почему так ? Только в этм примере ?

Хех. :-)
А как можно без SQL работать?
Аватара пользователя
Attid
долгожитель
Сообщения: 2588
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E
Контактная информация:

Сообщение Attid »

debi12345 писал(а):
а что такое LAST_INSERT_ID ??

Все нормальные сервера БД (PostgreSQL, FireBird, SQLite3,... )


для чего нужен последний автоинкриментный идентификатор мне расказывать не надо, но приведеный синтаксис не будет работать на моем firebird, а автор не удасужился сервер указать.


Я смотрю, вы работаете по старинке - то есть через низкоуровневый SQL. И это в 21-м веке. Почему так ? Только в этм примере ?

грид далеко не везде нужен. даже в 21 веке.


SeVer
попробуй другие компоненты доступа, хотябы сократишь круг поиска.
Аватара пользователя
debi12345
долгожитель
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение debi12345 »

Лично я крайне удивился, увидев попытки "ручного" использования LAST_INSERT_ID. Еще и ждут, чтобы оно работало всегда и везде :) У этого сервиса совсем другое предназначение, и обычно он вытаскивается не через SQL, а через API .
А чем нормальные нумераторы (sequence) не угодили ? Привязать их к ключевым полям, и потом только успевай вызывать "nextval ( для INSERT ) / currval ( для UPDATE )".
SeVer
незнакомец
Сообщения: 8
Зарегистрирован: 26.06.2007 16:06:38
Откуда: Чистополь
Контактная информация:

Сообщение SeVer »

Attid писал(а):SeVer
попробуй другие компоненты доступа, хотябы сократишь круг поиска.

Угу. Проблему решил путем отказа от компонентов, добавления в проект модуля mysq4 и использованием функции
ResID:= mysql_insert_id(MySock);
Для моей задачи самое то.
SeVer
незнакомец
Сообщения: 8
Зарегистрирован: 26.06.2007 16:06:38
Откуда: Чистополь
Контактная информация:

Сообщение SeVer »

debi12345 писал(а):Лично я крайне удивился, увидев попытки "ручного" использования LAST_INSERT_ID.

При "ручном" использовании обычно бывает намного больше гибкости. И почему бы не использовать то, что есть, если оно иной раз удобнее? Я еще и для PIC контроллеров на ассемблере, а не на си пишу, но это не для этого форума.
debi12345 писал(а):Еще и ждут, чтобы оно работало всегда и везде :) У этого сервиса совсем другое предназначение, и обычно он вытаскивается не через SQL, а через API .

А как еще узнать id последней вставленной записи? А что, в API SQL не используется????
debi12345 писал(а):А чем нормальные нумераторы (sequence) не угодили ? Привязать их к ключевым полям, и потом только успевай вызывать "nextval ( для INSERT ) / currval ( для UPDATE )".

Я и словов-то таких не знаю.
Аватара пользователя
Attid
долгожитель
Сообщения: 2588
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E
Контактная информация:

Сообщение Attid »

А как еще узнать id последней вставленной записи? А что, в API SQL не используется????

зависит от реализации иногда нет.
посмотри на реализацию mysql_insert_id() узнаешь как это делается в mysql. может и через sql, может нет.
Аватара пользователя
debi12345
долгожитель
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение debi12345 »

А как еще узнать id последней вставленной записи? А что, в API SQL не используется????

Каким конкретно пользователем ( в много-пользовательской системе ) ? 100% лочить (LOCK TABLE .. ) нужно таблицу - перед вставкой, и снимать только после обновления.

Я и словов-то таких не знаю

CREATE SEQUENCE table1_id_seq;

CREATE TABLE table1 (
id INETEGER DEFAULT nextval('"table1_id_seq"'),
f1 INTEGER,
f2 TEXT,
...
);

INSERT INTO table1 (f1, f2) VALUES (1,'one');
INSERT INTO table1 (id,f1, f2) VALUES (nextval('"table1_id_seq"'),1,'one');
UPDATE table1 SET f1=2, f2='two' WHERE id=currval('"table1_id_seq"');

В PostgreSQL атрибут "PRIMARY KEY" автоматически создает SEQUENCE и прописывает "DEFAULT ...".
100% в остальных серьезных движках типа Oracle, ЖарПтицы аналогичный сервис присутствует. Куда же без него ?
Ответить