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

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

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

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

Сообщение SeVer » 26.06.2007 16:47:08

Сабж.

Код: Выделить всё
      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;


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

Сообщение Attid » 26.06.2007 17:35:17

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

Сообщение SeVer » 26.06.2007 17:43:02

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

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

Сообщение Attid » 26.06.2007 20:19:01

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

ЗЫ. никогда не юзал MySQL и не кому не советую использовать кроме как в ВЕБ проэктах.
ЗЫЫ. думаю ошибка в sql синтаксисе.
Аватара пользователя
Attid
долгожитель
 
Сообщения: 2585
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E

Сообщение SeVer » 26.06.2007 20:45:39

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

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

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

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

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

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

Та же самая функция в MySQL-Front возвращает то, что надо.
Проблема в том, что и INSERT и LAST_INSERT_ID должны быть вызваны в одной сессии. Похоже, что каждый вызов ExecSQL и Open - это разные сессии.
SeVer
незнакомец
 
Сообщения: 8
Зарегистрирован: 26.06.2007 16:06:38
Откуда: Чистополь

Сообщение debi12345 » 26.06.2007 22:26:10

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

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

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

Он валидный не после SQL-команды "INSERT", а после вызова "dataset.Append" - что совсем не одно и то же.
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5759
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение SeVer » 26.06.2007 22:46:35

Значение ключевого поля в момент добавления записи, нужно для для авто-конструирования 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 - не важно.
SeVer
незнакомец
 
Сообщения: 8
Зарегистрирован: 26.06.2007 16:06:38
Откуда: Чистополь

Сообщение debi12345 » 27.06.2007 00:18:11

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


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

Я смотрю, вы работаете по старинке - то есть через низкоуровневый SQL. И это в 21-м веке. Почему так ? Только в этм примере ?
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5759
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение SeVer » 27.06.2007 00:47:45

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

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

Хех. :-)
А как можно без SQL работать?
SeVer
незнакомец
 
Сообщения: 8
Зарегистрирован: 26.06.2007 16:06:38
Откуда: Чистополь

Сообщение Attid » 27.06.2007 11:07:16

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

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


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


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

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


SeVer
попробуй другие компоненты доступа, хотябы сократишь круг поиска.
Аватара пользователя
Attid
долгожитель
 
Сообщения: 2585
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E

Сообщение debi12345 » 27.06.2007 13:12:35

Лично я крайне удивился, увидев попытки "ручного" использования LAST_INSERT_ID. Еще и ждут, чтобы оно работало всегда и везде :) У этого сервиса совсем другое предназначение, и обычно он вытаскивается не через SQL, а через API .
А чем нормальные нумераторы (sequence) не угодили ? Привязать их к ключевым полям, и потом только успевай вызывать "nextval ( для INSERT ) / currval ( для UPDATE )".
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5759
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение SeVer » 28.06.2007 01:46:35

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

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

Сообщение SeVer » 28.06.2007 01:52:04

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

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

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

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

Сообщение Attid » 28.06.2007 06:57:48

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

зависит от реализации иногда нет.
посмотри на реализацию mysql_insert_id() узнаешь как это делается в mysql. может и через sql, может нет.
Аватара пользователя
Attid
долгожитель
 
Сообщения: 2585
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E

Сообщение debi12345 » 28.06.2007 08:11:07

А как еще узнать 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, ЖарПтицы аналогичный сервис присутствует. Куда же без него ?
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5759
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

След.

Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 46

Рейтинг@Mail.ru