![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
(Oracle) Как правильно написать триггер для автоприсвоения ID [MySQL]
ANB © (2005-09-27 14:12:00)Попробовал сделать так :
create or replace trigger GT_Product_PK_TR
before insert on GT_Product
for each row
declare
begin
if :New.ID is null then
select GT_Product_SQ.Nextval into :New.ID from dual;
end if;
end GT_Product_PK_TR;
Получил проблему - если ID жестко задавать в инсертах, то сиквенс не мотается и потом лезут ошибки.
Переделал :
create or replace trigger GT_Product_PK_TR
before insert on GT_Product
for each row
declare
Cur_SQ number;
begin
if :New.ID is null then
select GT_Product_SQ.Nextval into :New.ID from dual;
else
select GT_Product_Firm_SQ.Currval into Cur_SQ from dual;
while (Cur_SQ < :New.ID) loop
select GT_Product_Firm_SQ.Nextval into Cur_SQ from dual;
end loop;
end if;
end GT_Product_PK_TR;
В таком варианте вроде, получше, но все равно можно нарваться на дублирование записей. Можно воткнуть еще проверку на существование уже сгенеренного ID и прокручивать сиквенс до нужного значения, но, во первых, полезут ошибки "таблица мутирует", во вторых это ничего особо не даст, т.к. если я умудрюсь в двух разных сессиях сгенерить один и тот же ID, то про триггер на них никак не поругается, так как записи еще не закоммичены, а проблема вылезет при коммите. Хотя, возможно, я не так понял механизм транзакций.
Sergey13 (2005-09-29 12:46:00) [61]2 [49] ANB © (29.09.05 12:40)
А если какому дураку захочется ввести ИД=максимальному значению сиквенса, или около того?
ANB (2005-09-29 12:40:00) [62]
> Sergey13 © (29.09.05 12:33) [48]
- хм. А таки я попробую. Кстати, таки придется втыкать проверку и в Is null. Может кому всеблится отключить триггер, накидать записей, а потом включить. И сиквенс таки не перемотается. Никто не знает, как не напарываться на мутацию при обращении к этой же таблице в триггерре ?
Sergey13 (2005-09-29 12:33:00) [63]2ANB © (29.09.05 12:25)
Добраться до значения сиквенса ведь можно и через
select * from all_sequences
Может это тебя натолкнет на что полезное?
Хотя я по прежнему считаю, что ты перемудриваешь. 8-)
ANB (2005-09-29 12:25:00) [64]
> Fay © (29.09.05 12:21) [46]
- да нарвался уже. Я же постил. Кстати, в НЕКОТОРЫХ случаях может и не дать, но редко. Как раз в моем случае я на нее сразу нарвался. Попробовал заменить на nextval, но обнаружил уже логическую ошибку : если в клиентском приложении я ручками мотаю сиквенс и присваиваю жестко полученный ID. то триггер проматывает его лишний раз.
Fay (2005-09-29 12:21:00) [65]2 ANB © (27.09.05 15:45) [19]
Обратите внимание на [2]. Sergey13 совершенно прав:
>> select GT_Product_Firm_SQ.Currval
>> может и ошибку дать, если сессия еще не дергала этот сиквенс.
Могу только добавить, что не "может" дать ошибку, а ДАСТ 8)
ANB (2005-09-29 11:47:00) [66]
> Тогда это будет не твоя проблема. 8-)
- так не солидно. Мне ж за это денежку заплатят. Сверх зарплаты.
Sergey13 (2005-09-29 11:05:00) [67]2 [43] ANB © (29.09.05 10:39)
> А если встеблится добавить скриптиком чего-нибудь ? Со связками ?
Скриптик писать надо с учетом этого или чистить за собой, как уже советовалось в [25]. Это, ИМХО, разумнее, нежели (повторяюсь опять же) "лишний код в базе годами крутить"
>Могу же я себе позволить работать в MS SQL напрямую с автоинкрементарным полем и при этом ничего не ломается ?
Про это не знаю, не работал.
>Плюс пока приклад пишу я, а вот развивать - вовсе не факт.
Тогда это будет не твоя проблема. 8-)
ANB (2005-09-29 10:39:00) [68]
> Sergey13 © (29.09.05 10:34) [42]
А если встеблится добавить скриптиком чего-нибудь ? Со связками ? Могу же я себе позволить работать в MS SQL напрямую с автоинкрементарным полем и при этом ничего не ломается ? Плюс пока приклад пишу я, а вот развивать - вовсе не факт.
Sergey13 (2005-09-29 10:34:00) [69]2[41] ANB © (29.09.05 10:05)
>- не, под клиентом я подразумевал клиентское приложение.
Я догадался. 8-)
Потому и спросил. Если в прикладе прописана вставка ИД из сиквенса, как в таблице появятся левые (не от туда) значения? Из "Плюсов" и "Девелоперов"? Так тогда надо безопасностью заниматься, а не сиквенсы "выравнивать" .
ИМХО.
ANB (2005-09-29 10:05:00) [70]
> Sergey13 © (29.09.05 09:52) [40]
- не, под клиентом я подразумевал клиентское приложение. Я видел уже несколько решений, но они все не очень универсальны и в каждом есть возможность граблей. Просто сейчас рисую небольшой проектик и на нем хотел бы отработать технологию. Если юзер ручками введет дубль, то, ессно, правильным будет поругаться и послать его.
Sergey13 (2005-09-29 09:52:00) [71]2[39] ANB © (29.09.05 09:15)
А откуда ноги растут у твоей озабоченности? С чего бы вдруг юзер стал вводить левые значения и каким образом? Шаловливыми ручками всегда можно вмешаться и на каждый узерский чих заплат не напишешь. ИМХО.
ANB (2005-09-29 09:15:00) [72]Таки не нравиться мне то, что получилось. Получается, клиент должен сам заботится о синхронизации сиквенса и ID таблицы. Может таки при ID is null проверять в цикле, что очередное значение сиквенса не конфликтует с ID ? В одной конторе так и сделано, но вылезает другая грабля - по одной записи нормально вставляются, а при пакетной вставке вылезает мутация таблицы.
mr.il (2005-09-27 17:06:00) [73]На счет пакета полностью согласен. У меня был вопрос в принципе, об исключении из клиента информации о правилах вставки.
Отдельно спасибо Sergey13, об этом: B>returnung id into :id я не знал
ANB (2005-09-27 17:03:00) [74]
> Sergey13 © (27.09.05 16:59) [36]
- эт точно. Просто у нас в конторе такой подход.
Sergey13 (2005-09-27 16:59:00) [75]2[34] ANB © (27.09.05 16:52)
> Вообще то обычно процедуры вставки в пакет запихивают. А заодно и для апдейта.
А я обычновообще ХП для этого не использую. Это дело вкуса и конкретных условий, ИМХО.
ANB (2005-09-27 16:53:00) [76]ЗЫ. В моем случае оптимально
> Sergey13 © (27.09.05 16:50) [33]
(Так примерно ODAC и делает)
ANB (2005-09-27 16:52:00) [77]
> mr.il © (27.09.05 16:44) [32]
Вообще то обычно процедуры вставки в пакет запихивают. А заодно и для апдейта. Потом конечным пользователям даются права на чтение из таблицы, и на исполнение этих процедур. А в теле процедуры проверяются бизнес правила и права пользователя на изменения таблицы.
Но мне для этой задачи этого не нужно. Так как защита не нужна. Чисто внутренний проект.
Sergey13 (2005-09-27 16:50:00) [78]2 [32] mr.il © (27.09.05 16:44)
И чем это проще чем (абстрактно)
insert into Таблица (ид_поле, имя_поле) values (секвенс.NextVal, имя) returnung id into :id
?
mr.il (2005-09-27 16:44:00) [79]Ну да, ХП. Ну абстрактно так:
Процедура (Имя Строка)
IS (ид Число)
Тело процедуры
ид = секвенс.NextVal
insert into Таблица (ид_поле, имя_поле)
values (ид, имя)
Прошу простить, пишу абстракно, проверить не на чем.
ANB (2005-09-27 16:36:00) [80]
> Sergey13 © (27.09.05 16:31) [30]
- сделал, как ты подсказал. Вернул триггер к первому варианту, а после вставок выполняю перемотку сиквенсов. Вроде, работает.
ЗЫ. Есть куча вариантов через ХП, присвоение ID прямо в инсерте, но они накладывают ограничения на возможности работы с таблицей и ID. При наличии триггера я могу пользоваться как всеми уже указанными способами, так и лениво инсертить в таблицу без указания ID и все будет работать.