Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.11.13;
Скачать: CL | DM;

Вниз

(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;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.027 c
5-1109235757
Павел
2005-02-24 12:02
2005.11.13
Поясните свойство ComponentState


2-1129803546
Arimag
2005-10-20 14:19
2005.11.13
Как проиграть свой собственный звук?


2-1129569313
Bogdan1024
2005-10-17 21:15
2005.11.13
типо createprocess


4-1125218505
rolex
2005-08-28 12:41
2005.11.13
Функция показывает, что в папке Prefetch файлы в использовании!


9-1119916688
Xenon
2005-06-28 03:58
2005.11.13
Обновление темы, насчет скринов к моей игре