Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 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.56 MB
Время: 0.036 c
14-1130062668
Nikolay M.
2005-10-23 14:17
2005.11.13
Никому не нужны программы на 5 25 для Spectrum?


14-1130150338
syte_ser78
2005-10-24 14:38
2005.11.13
время компиляции проекта


14-1129631221
DelphiN!
2005-10-18 14:27
2005.11.13
Как правильно оценить стоимость программы


14-1130171214
Fl@sh
2005-10-24 20:26
2005.11.13
Тайксер &amp; Пачеко


2-1129442715
serg128
2005-10-16 10:05
2005.11.13
Как заменить первую маленькую букву на большую?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский