![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
ID последней добавленной записи [D7, любая СУБД]
DVM © (2008-09-04 12:03:00)Вопрос тут уже вроде всплывал тут, но в основном касался каких то конкретных СУБД, например Access. Мне же нужен по возможности универсальный вариант, ну пусть хотя бы одинаково работающий в Access, MySQL, MSSQL, Oracle.
Посредством SQL запроса в таблицу добавляется некая запись. Одним из полей таблицы является автоинкрементное поле счетчик (ID).
После добавления записи в таблицу мне нужно получить значение поля ID для этой добавленной записи.
Как в таких случаях обычно поступают? Писать разный код для разных СУБД? Ввести свое доп. поле в которое пихать собственноручно сгенерированное чудо типа GUID и сразу после добавления находить запись по этому полю?
Кщд (2009-03-17 12:15:00) [1]>clickmaker © (12.03.09 14:36) [82]
это чем-то лучше GUID?
пример?
Кщд (2009-03-17 12:04:00) [2]>Cobalt © (12.03.09 14:49) [83]
>1. всякое удобство чего-то стОит. кстати, можно и протестировать скорость, >прежде чем прислушиваться к советам всяких там... ;-)
почему бы, собственно, не использовать GUID в качестве ID?
к чему все эти пляски с очисткой и поиском ID?
про псевдоуникальность GUID давно уже поперетерли - да, конфликт возможен, но крайнемаловероятен
>2. Если в индексе одновременно (в течении долей секунды) будет не более >пару записей - то, полагаю, незначительно.
в некоторых СУБД null-значения хранятся в индексе
Petr V. Abramov (2009-03-12 15:12:00) [3]
> Не слишком-ли шикарно, а?
зато СУБД-независимо ;)
Cobalt (2009-03-12 14:49:00) [4]
> Ega23 © (12.03.09 14:36) [81]
>
> > И потом, можно это поле очищать сразу же по получению ID,
> > и индекс по нему (Guid-у) строить.
>
> 1. Если очищать, то у тебя процесс добавления записи выливается
> в 3 отдельных запроса: Insert, Select, Update. Не слишком- ли шикарно, а?
> 2. Строить индекс по строковому полю - это сильно. Прикинь,
> сколько вставка (с перестроением индекса) будет занимать?
>
1. всякое удобство чего-то стОит. кстати, можно и протестировать скорость, прежде чем прислушиваться к советам всяких там... ;-)
2. Если в индексе одновременно (в течении долей секунды) будет не более пару записей - то, полагаю, незначительно.
Ega23 (2009-03-12 14:36:00) [5]
> И потом, можно это поле очищать сразу же по получению ID,
> и индекс по нему (Guid-у) строить.
1. Если очищать, то у тебя процесс добавления записи выливается в 3 отдельных запроса: Insert, Select, Update. Не слишком-ли шикарно, а?
2. Строить индекс по строковому полю - это сильно. Прикинь, сколько вставка (с перестроением индекса) будет занимать?
clickmaker (2009-03-12 14:36:00) [6]> [0] DVM © (04.09.08 12:03)
используй дату в качестве основы для генерации Ид. На клиенте.
Cobalt (2009-03-12 14:27:00) [7]
> Ega23 © (12.03.09 14:11) [79]
> Вот теперь прикинь: в таблице миллион записей. Да пусть даже не миллион,
> а 10000. Сколько у тебя займёт поиск по точному сравнению строк?
А это уже второй вопрос, профессор :-)
За всё надо платить.
И потом, можно это поле очищать сразу же по получению ID, и индекс по нему (Guid-у) строить.
Или воспользоваться вторым вариантом.
Главное требование было - работоспособность на разных базах.
Ega23 (2009-03-12 14:11:00) [8]
> Cobalt © (12.03.09 14:02) [77]
Вот теперь прикинь: в таблице миллион записей. Да пусть даже не миллион, а 10000. Сколько у тебя займёт поиск по точному сравнению строк?
Cobalt (2009-03-12 14:04:00) [9]2 Кщд (12.03.09 13:51) [76]
P.S.
Если, конечно, таблица не откладывает изменения на клиенте, а сразу производит запись в базу.
Cobalt (2009-03-12 14:02:00) [10]
> Ega23 © (12.03.09 13:40) [75]
GUID будет генерить клиент, который, собственно, и хочет знать Id-ик только что вставленной им же записи.
А varchar, полагаю, у всех баз есть.
Условно:
ExecSQL('Insert into mytable (name, guid) values ('Pupkin', '{54788324-43431254-53-5235-25-2}')
Затем
MyQuery.SQL.Text := 'Select ID from mytable
where guid = ''{54788324-43431254-53-5235-25-2}''''
id := MyQuery.ParamByName('id').AsInteger;
> Кщд (12.03.09 13:51) [76]
>
> >Cobalt © (12.03.09 13:28) [74]
> >Полагаю, что проще будет использовать Таблицу, и делать
> в неё вставку. а после Post читать поле ID.
> это как?
что-то типа такого:
With MyTable do
begin
Insert;
FieldByName('name') := 'pupkin';
FieldByName('guid') := '{54788324-43431254-53-5235-25-2}';
Post;
id := FieldByName('id');
end;
Кщд (2009-03-12 13:51:00) [11]>Cobalt © (12.03.09 13:28) [74]
>Полагаю, что проще будет использовать Таблицу, и делать в неё вставку. а после Post читать поле ID.
это как?
Ega23 (2009-03-12 13:40:00) [12]GUID не все базы поддерживают.
GUID не все базу умеют генерить
Cobalt (2009-03-12 13:28:00) [13]Первое решение, для Insert:
В таблицу добавляете поле varchar
при вставке туда записывается GUID
После вставки делается выборка ID-ка по этому GUID
Потом это GUID-поле можно/нужно очистить
Работает для одной записи, на любых базах.
Полагаю, что и для нескольких записей такой алгоритм тоже сработает.
Второе решение, с использованием таблицы, куда делается вставка:
Полагаю, что проще будет использовать Таблицу, и делать в неё вставку. а после Post читать поле ID.
Кщд (2009-03-12 11:49:00) [14]>Ega23 © (12.03.09 10:17) [72]
это был пример навскидку(92 читал наискосок; 2003-ий, увы мне, не читал вовсе; учился по 99-му - поэтому его и привел), где точно упоминается об уровнях изоляции
очень не думаю, что в 2003-ем стандарте произошли изменения по части уровней изоляции
Ega23 (2009-03-12 10:17:00) [15]
> ANSI SQL 99
Староват стандарт. ЕМНИП, как минимум 2003 года уже был. А возможно и позже, там дополнения где-то раз в год-полтора выходят..
Ega23 (2009-03-12 10:14:00) [16]
> В свое время в IB делал по хранимке на каждую таблицу. Входные
> параметры - значения полей, а на выходе был присвоенный
> id-к. Внутри хранимки вызывался генератор, потом с полученным
> значением делался insert в таблицу и то же значение возвращалось
> процедурой.
>
Я вообще всегда так делаю, что под MSSQL, что под Postgres. Очень удобно.
Кщд (2009-03-12 06:36:00) [17]>фыва (11.03.09 19:57) [67]
ссылка нужна для подтверждения весьма спорного утверждения
здесь же достаточно просто открыть документацию по стандарту ANSI SQL 99
YurikGL (2009-03-11 20:15:00) [18]вот... даже код нашел
CREATE PROCEDURE ADDUPR (
naimenovan varchar(50),
primech varchar(200))
returns (
id integer)
as
begin
ID = gen_id(g_upr, 1);
insert into upr (IdUpr,Naimenovan,Primech) values(:ID,:NAIMENOVAN,:primech);
end
YurikGL (2009-03-11 20:09:00) [19]В свое время в IB делал по хранимке на каждую таблицу. Входные параметры - значения полей, а на выходе был присвоенный id-к. Внутри хранимки вызывался генератор, потом с полученным значением делался insert в таблицу и то же значение возвращалось процедурой.
фыва (2009-03-11 19:57:00) [20]
> >В стандарте SQL определены четыре уровня изоляции: READ
> UNCOMMITTED, READ COMMITTED, REPEATABLE READ и SERIALIZABLE.
ссылку на данное утверждение в стандарте SQL, пожалйста