Russian Qt Forum

Qt => Базы данных => Тема начата: RomiX от Апрель 09, 2011, 14:48



Название: получить id вставленной строки
Отправлено: RomiX от Апрель 09, 2011, 14:48
выполняю примерно такой запрос INSERT INTO `table` (`name`) VALUES('No name')
как мне получить id который был присвоен только что вставленной записи?
например phpMyAdmin после записи пишет что то вроде:Inserted row id: 14
база MySql


Название: Re: получить id вставленной строки
Отправлено: Nimbus от Апрель 09, 2011, 15:12
SELECT LAST_INSERT_ID();


Название: Re: получить id вставленной строки
Отправлено: RomiX от Апрель 09, 2011, 15:25
а тоесть id сам не возвращается, прост о не хотел делать дополнительных запросов, спс


Название: Re: получить id вставленной строки
Отправлено: NicK от Апрель 09, 2011, 15:38
Код
C++ (Qt)
...
QSqlQuery query(db);
...
if query.exec("INSERT INTO `table` (`name`) VALUES('No name')"){
      qDebug()<<"last inserted id:"<<query.lastInsertId().toString();
};
 


Название: Re: получить id вставленной строки
Отправлено: Nimbus от Апрель 09, 2011, 15:53
а тоесть id сам не возвращается, прост о не хотел делать дополнительных запросов, спс
Фактически, запрос всё равно делается. Вот в Оракле для этого не нужно делать дополнительного запроса :)


Название: Re: получить id вставленной строки
Отправлено: break от Апрель 09, 2011, 17:18
Для данных целей в FB использовал такой метод

1) сам дергал генератор для получения ID
2) использовал это полученное ID для вставляемой строки, тем самым уже зная его

Все это в связи с тем что в пределах выполняемой транзакции нельзя было увидеть ID вставленной строки до подтверждения или отмены ее.

Может быть еще как то returning может помочь (сам не использовал - была дискуссия в теме про альтернативный драйвер Qt FB).


Название: Re: получить id вставленной строки
Отправлено: johnpion от Апрель 12, 2011, 15:46
В SQLLite есть полезная системныя таблица для этих целей.
Код:
SELECT seq FROM sqlite_sequence WHERE name = 'actions'


Название: Re: получить id вставленной строки
Отправлено: asvil от Апрель 12, 2011, 15:57
Как рад, что пользуюсь Postgres. Все ваши БД отстают по удобству использования.

Код:
insert into table values a, b, c, d returning *

В очень мною ненавидимом оракле 10 приходиться делать связывание OUT переменных, что как оказалось чревато сегфолтом, если под данную переменную не выделить память, хотя бы вот так QVariant(QString(' ', 10)). Первичный ключ текстовый в данном случае.
В целом оракл оставляет желать лучшего в плане удоства программирования. Взять хотя бы невозможность навески одного триггера на несколько таблиц. Или невозможность модификации сиквенса. Кто там из менеджеров/инженеров вообще додумался до такой хрени, а?




Название: Re: получить id вставленной строки
Отправлено: break от Апрель 12, 2011, 16:51
Цитировать
Как рад, что пользуюсь Postgres. Все ваши БД отстают по удобству использования.

В Firebird 2.1 такой запрос вполне корректно работает и возвращает значение вставленного ID
Код:
insert into ACTIVITY(NAME)
values ('0111')
returning ROW_ID
Уверен и во многих других БД это рабоатет, вопрос был в том что returning не поддерживался стандартным драйвером Qt для Interbase/Firebird.

Цитировать
Первичный ключ текстовый в данном случае.
Сомнительное решение

Цитировать
Взять хотя бы невозможность навески одного триггера на несколько таблиц.
Зачем это нужно? Триггеры для отработки эконом. логики все равно для каждой таблицы свои, поля то в таблицах разные. А триггеры формирования пустых ROW_ID или подобные настолько просты, что нет проблем их иметь кадждый на свою таблицу.


Название: Re: получить id вставленной строки
Отправлено: asvil от Апрель 12, 2011, 17:15
Цитировать
insert into ACTIVITY(NAME)
values ('0111')
returning ROW_ID
ROW_ID в данном случае псевдо-колонка? Если да, это костыль. Если это имя столбца, то API firebird client библиотеки возможно непродумано. В постгри клиенте есть одна большая PGresult* PQexec(SQL_STRING); Соответственно Кутешники поняли, что какой бы SQL пользователь не выполнил ему всегда надо отдать QSqlResult пусть даже пустой.

Цитировать
Сомнительное решение
Не спорю. Но даже на int64(простите не знаю имя типа oracle), нужно сделать как минимум QVariant(QVariant::qlonglong) для OUT переменной и только после сделать addBindValue.

Цитировать
Зачем это нужно?
Есть такая занимательная игра у менеджеров, называется "больше велосипедов, хороших и красивых". Задача: самодельная репликация для оракла. Если бы у меня была возможность навесить один большой триггер на все таблицы, я бы в нем используя хм... "интроспекцию" делал insert|update|delete в прилинкованную базу.
Итого: репликация отключается/включается одним большим триггером, который потом для скорости переписывается на сях. У вас тоже можно писать модули на сях?
Ан нет я сейчас буду лепить триггера, много хороших и красивых.

Цитировать
А триггеры формирования пустых ROW_ID....
Вы имеете ввиду автогенерацию значений для первичных и не обязательно ключей?
Сравните

Код:
create table(
   id bigserial;
   name text;
);
Который разворачивается в
Код:
create sequence table_id_seq int64 start 0 end 99..99 increment 1;
create table(
   id int64 default next_val(table_id_seq);
   name text;
);
И вот уже никаких триггеров не нужно для такой задачи.


Кстати как-то увидел:
Код:
if :NEW.id = null then
   select max(id) + 1 into :new.id from table;
end if;


Название: Re: получить id вставленной строки
Отправлено: break от Апрель 12, 2011, 23:47
Цитировать
ROW_ID в данном случае псевдо-колонка? Если да, это костыль. Если это имя столбца, то API firebird client библиотеки возможно непродумано.
это не псевдо колонка, а обычная колонка, кстати по сути конкретно от FB в Postgre модификатор RETURNING мало чем отличается.
Цитировать
У вас тоже можно писать модули на сях?
FB поддерживает UDF как и многи сервера БД

Цитировать
Вы имеете ввиду автогенерацию значений для первичных и не обязательно ключей?
да
Цитировать
И вот уже никаких триггеров не нужно для такой задачи.
И что это круто?
А такое типа не круто:
Код:
SET TERM ^ ;
CREATE TRIGGER ACTIVITY_BI FOR ACTIVITY ACTIVE
BEFORE INSERT POSITION 0
as
begin
  if (new.row_id is null) then
    new.row_id = gen_id(gen_activity_id,1);
end^
SET TERM ; ^

Я вот например не уверен на 100% что спецописания полей лучше использовать для автогенерации значений, чем триггеры - как минимум одинаково. Преимущество триггеров в их модульности, возможности навесить несколько триггеров и упорядочить их, для спец логики нельзя же вводить новые спец описания на таблицу - например если нельзя удалять запись с ID=1, или со списком ID хранящихся в другой таблице.

Цитировать
Есть такая занимательная игра у менеджеров, называется "больше велосипедов, хороших и красивых".
Это скорее игры умников программистов старающихся выпендриться, перед менеджерами стоят как правило типовые задачи учета и анализа.
Вообще задача триггера для таблицы сработать и выполнить код в момент событий вставки, удаления, обновления записи. Непонятно как для разных таблиц можно использовать в таком случае один код. Но уж если сильно хочется можно написать Хранимую Процедуру, части которой переписаны на Сях и вызывать ее из триггеров заглушек расставленных по таблицам.

А вообще задача кажется весьма надуманной и неконкретной - скорее для писькомерства Postgre с другими БД.


Название: Re: получить id вставленной строки
Отправлено: asvil от Апрель 13, 2011, 09:48
Цитировать
А такое типа не круто:
Дело вкуса. Предпочитаю лениться. Моя крутизна в том, что у меня одна строка делает одну функцию (автоинкремент). Мне не нужна мощность/расширяемость.

Цитировать
Это скорее игры умников программистов...
В том числе. Но речь таки не об этом. Речь действительно о пипиське. У postgre самая большая из открытых программ. И далеко не самая маленькая среди коммерческих баз данных.

Я предпочитаю лениться, а не выпендриваться, соответственно, писать все 78 триггеров на таблицы мне не улыбается никак. А готовая репликация для оракла стоит денег, которых соответственно нет.

Если Вам не сложно, дайте задачу реалистичнее и мы с Вами будем меряться.


Название: Re: получить id вставленной строки
Отправлено: break от Апрель 13, 2011, 11:15
Мне нет никакого интереса меряться, более того я не уверен что postgre не самая крутая БД. Может и самая. Но это не важно. Будет интерессная прибыльная задача с которой не справится FB или по Т.З. нельзя будет его использовать, я буду изучать что-то другое, пока мне это не нужно.