Форум: "Базы";
Текущий архив: 2005.11.13;
Скачать: [xml.tar.bz2];
Вниз(Oracle) Как правильно написать триггер для автоприсвоения ID Найти похожие ветки
← →
ANB © (2005-09-27 14:12) [0]Попробовал сделать так :
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, то про триггер на них никак не поругается, так как записи еще не закоммичены, а проблема вылезет при коммите. Хотя, возможно, я не так понял механизм транзакций.
← →
Андрей Жук © (2005-09-27 14:18) [1]В MySQL появились триггеры???
← →
Sergey13 © (2005-09-27 14:20) [2]2ANB © (27.09.05 14:12)
Че-то ты мудришь, ИМХО.
>если ID жестко задавать в инсертах
Как жестко? Нафига жестко?
Можно и гвозди конечно микроскопом забивать. Вопрос - зачем?
select GT_Product_Firm_SQ.Currval
может и ошибку дать, если сессия еще не дергала этот сиквенс.
← →
kesha © (2005-09-27 14:26) [3]if :new.ID is null then
SELECT GT_Product_SQ.Nextval into :New.ID from dual;
end if;
CREATE SEQUENCE "xxx"."GT_Product_SQ" INCREMENT BY 1 START
WITH 1 MAXVALUE 1.0E28 MINVALUE 1 CYCLE
CACHE 20 ORDER;
pri vstavke "ID" - vsegda NULL
← →
Sergey13 © (2005-09-27 14:31) [4]2[3] kesha © (27.09.05 14:26)
Это все зачем?
Это ты все в тригер хочешь написать? И ты думаешь будет работать? Мне кажется, даже не откомпилится.
Да и по смыслу... вернее смысла я не вижу.
← →
Андрей Жук © (2005-09-27 14:42) [5]Как делаю я. У меня есть процедура, которая по имени таблицы возвращает следующий ID по сиквенсу. Процедурка отрабатывает мгновенно. После чего на клиенте есть уже уникальный ID, который и вставляем в insert.
← →
kesha © (2005-09-27 14:56) [6]
> Sergey13 © (27.09.05 14:31) [4]
CREATE SEQUENCE -> ne v triggere, a v base.
ANB:
esli tebe posle Insert gde-to nuzhen ID, to kak [5], tolko ne Procedure a Function:
Inset into Table(ID, Field1) Values(Get_New_ID(Table), xxx);
esli tebe ID ne nuzgen:
Inset into Table(Field1) Values(xxx);
← →
DenK_vrtz © (2005-09-27 15:09) [7]
> if :New.ID is null then
>
зачем это условие? Если вставка данных то :New.ID изначально null
select sqИмяПоследовательности.nextval into :new.id from dual; и больше никаких извращений
← →
Sergey13 © (2005-09-27 15:10) [8]2[6] kesha © (27.09.05 14:56)
Тогда я не понял твоего
>pri vstavke "ID" - vsegda NULL
>esli tebe posle Insert gde-to nuzhen ID, to kak [5], tolko ne Procedure a Function:
Inset into Table(ID, Field1) Values(Get_New_ID(Table), xxx);
Как ты его отсюда получишь на клиенте?
← →
Sergey13 © (2005-09-27 15:17) [9]2[7] DenK_vrtz © (27.09.05 15:09)
>зачем это условие? Если вставка данных то :New.ID изначально null
Inset into Table(ID, Field1) Values(99999999, "xxx")
и где тут NULL?
← →
DenK_vrtz © (2005-09-27 15:20) [10]>Sergey13 © (27.09.05 15:17) [9]
Зачем явно задавать значение :new.ID, если он берется из последовательности и формируется автоматически?
← →
DenK_vrtz © (2005-09-27 15:21) [11]т.е. не он, а оно! :)
← →
Курдль © (2005-09-27 15:27) [12]Странное сочетание "oracle + MySQL" :)
Надеюсь, что это очепятка.
А как подключаетесь к ораклу? Если при помощи наиболее оптимальных для Delphi и испытанных в боях компонентов DOA, то им достаточно указать последовательность, связанную с идентификатором и они все сделают сами!
← →
Sergey13 © (2005-09-27 15:28) [13]2[10] DenK_vrtz © (27.09.05 15:20)
Его можно (вернее нужно) взять оттуда-же, но до вставки. Например, что бы знать что вставлять в поле связи детальной таблицы.
← →
Desdechado © (2005-09-27 15:29) [14]2 ANB [0]
первого варианта достаточно, если не будешь мудрить с придумыванием из головы ID для вставки в таблицу
после INSERT можно узнать ID перезапросом по уникальной комбинации полей или используя фичу Оракла:
INSERT .... RETURNING ... INTO ...
← →
DenK_vrtz © (2005-09-27 15:33) [15]>Sergey13 © (27.09.05 15:28) [13]
Или я чего пропустил, или детальные таблицы причем? :)
← →
ANB © (2005-09-27 15:38) [16]Ой ой. Как много ответов.
1. Отмечал оракл, но так как на форуме бага, то написал еще и в скобках тип БД.
2. Везде на всякий случай и стоит первый вариант (если ручками изнутри табличку править, то очень удобно), но нарвался на проблему : после создания таблиц схемы я скриптом заполняю начальные данные (справочники) и мне удобно писать там константы, а сиквенс при этом не перемотался и когда начинаешь таблицу корректировать ручками (тут уже все равно, ODAC генерит ID или я сам) получаю ошибку дублирования PK.
2-го варианта будет достаточно ?
ЗЫ. Вернуть ID на клиента, если припрет, не проблема через returning.
← →
Sergey13 © (2005-09-27 15:40) [17]2[15] DenK_vrtz © (27.09.05 15:33)
>Или я чего пропустил, или детальные таблицы причем? :)
При том, что они встречаются. И достаточно часто. И в них иногда надо что-то вставлять. 8-)
← →
Sergey13 © (2005-09-27 15:44) [18]2[16] ANB © (27.09.05 15:38)
Создавай сиквкенсы и тригера после заполнения. Начальное значение для сиквенса бери как Max+1 ИДшника таблицы.
← →
ANB © (2005-09-27 15:45) [19]Прошу прощения, в этом триггере и правда была синтаксическая ошибка. Вот так он выглядит в реале :
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_Sq.currval
into Cur_Sq
from dual;
while (Cur_Sq < :new.ID) loop
select Gt_Product_Sq.nextval
into Cur_Sq
from dual;
end loop;
end if;
end Gt_Product_pk_Tr;
← →
ANB © (2005-09-27 15:46) [20]
> Sergey13 © (27.09.05 15:44) [18]
- думал и над этим. Как то неуниверсально получится.
← →
Desdechado © (2005-09-27 15:51) [21]причем тут универсальность, если заполнение таблиц скриптом выполняется единожды?
← →
ANB © (2005-09-27 15:51) [22]
> Sergey13 © (27.09.05 14:20) [2]
- точно, ошибку выдала. Вот блин.
← →
ANB © (2005-09-27 15:52) [23]
> Desdechado © (27.09.05 15:51) [21]
- то есть лучше вернуться к первому варианту ?
← →
DenK_vrtz © (2005-09-27 15:56) [24]>ANB © (27.09.05 15:46) [20]
Если вариант Sergey13 © (27.09.05 15:44) [18] не устраивает(и почему он не универсальный?), то создать две последовательности. Первая идет по четным - вставляешь данные ты, вторая идет по нечетным - вставляет данные кто-то другой
← →
Sergey13 © (2005-09-27 15:57) [25]2[23] ANB © (27.09.05 15:52)
ИМХО, да. Можно, если хочется сильно, отдельный скрипт наваять на коррекцию сиквенсов по текущим значениям таблиц. Все лучше, чем лишний код в базе годами крутить.
← →
kesha © (2005-09-27 16:07) [26]
> Sergey13 © (27.09.05 15:10) [8]
smotrja dlja 4ego tebe etot ID:
1: esli tol"ko Insert (vstavili i sabili) -> togda NULL
2: esli Insert delaet Function, kotoraja fozvrazhaet ID -> togda sna4ala
.NEXTVAL into xxx, potom Insert s etim xxx
← →
Sergey13 © (2005-09-27 16:24) [27]2[26] kesha © (27.09.05 16:07)
Если честно - моя твоя не сильно понимай.
← →
mr.IL © (2005-09-27 16:27) [28]Народ, а не проще написать СП , в нее передавать значения будущей записи, в ней получать значение генератора, делать инсерт, а из нее получать ид.
← →
ANB © (2005-09-27 16:27) [29]
> Sergey13 © (27.09.05 16:24) [27]
- если честно - моя его тоже не понимай.
← →
Sergey13 © (2005-09-27 16:31) [30]2 [28] mr.IL © (27.09.05 16:27)
А по твоему проще? И что будет в этой СП (ХП наверное?)? Тот же запрос?
← →
ANB © (2005-09-27 16:36) [31]
> Sergey13 © (27.09.05 16:31) [30]
- сделал, как ты подсказал. Вернул триггер к первому варианту, а после вставок выполняю перемотку сиквенсов. Вроде, работает.
ЗЫ. Есть куча вариантов через ХП, присвоение ID прямо в инсерте, но они накладывают ограничения на возможности работы с таблицей и ID. При наличии триггера я могу пользоваться как всеми уже указанными способами, так и лениво инсертить в таблицу без указания ID и все будет работать.
← →
mr.il © (2005-09-27 16:44) [32]Ну да, ХП. Ну абстрактно так:
Процедура (Имя Строка)
IS (ид Число)
Тело процедуры
ид = секвенс.NextVal
insert into Таблица (ид_поле, имя_поле)
values (ид, имя)
Прошу простить, пишу абстракно, проверить не на чем.
← →
Sergey13 © (2005-09-27 16:50) [33]2 [32] mr.il © (27.09.05 16:44)
И чем это проще чем (абстрактно)
insert into Таблица (ид_поле, имя_поле) values (секвенс.NextVal, имя) returnung id into :id
?
← →
ANB © (2005-09-27 16:52) [34]
> mr.il © (27.09.05 16:44) [32]
Вообще то обычно процедуры вставки в пакет запихивают. А заодно и для апдейта. Потом конечным пользователям даются права на чтение из таблицы, и на исполнение этих процедур. А в теле процедуры проверяются бизнес правила и права пользователя на изменения таблицы.
Но мне для этой задачи этого не нужно. Так как защита не нужна. Чисто внутренний проект.
← →
ANB © (2005-09-27 16:53) [35]ЗЫ. В моем случае оптимально
> Sergey13 © (27.09.05 16:50) [33]
(Так примерно ODAC и делает)
← →
Sergey13 © (2005-09-27 16:59) [36]2[34] ANB © (27.09.05 16:52)
> Вообще то обычно процедуры вставки в пакет запихивают. А заодно и для апдейта.
А я обычно вообще ХП для этого не использую. Это дело вкуса и конкретных условий, ИМХО.
← →
ANB © (2005-09-27 17:03) [37]
> Sergey13 © (27.09.05 16:59) [36]
- эт точно. Просто у нас в конторе такой подход.
← →
mr.il © (2005-09-27 17:06) [38]На счет пакета полностью согласен. У меня был вопрос в принципе, об исключении из клиента информации о правилах вставки.
Отдельно спасибо Sergey13, об этом: B>returnung id into :id я не знал
← →
ANB © (2005-09-29 09:15) [39]Таки не нравиться мне то, что получилось. Получается, клиент должен сам заботится о синхронизации сиквенса и ID таблицы. Может таки при ID is null проверять в цикле, что очередное значение сиквенса не конфликтует с ID ? В одной конторе так и сделано, но вылезает другая грабля - по одной записи нормально вставляются, а при пакетной вставке вылезает мутация таблицы.
← →
Sergey13 © (2005-09-29 09:52) [40]2[39] ANB © (29.09.05 09:15)
А откуда ноги растут у твоей озабоченности? С чего бы вдруг юзер стал вводить левые значения и каким образом? Шаловливыми ручками всегда можно вмешаться и на каждый узерский чих заплат не напишешь. ИМХО.
Страницы: 1 2 3 вся ветка
Форум: "Базы";
Текущий архив: 2005.11.13;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.041 c