Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2005.11.13;
Скачать: [xml.tar.bz2];

Вниз

(Oracle) Как правильно написать триггер для автоприсвоения ID   Найти похожие ветки 

 
Sergey13 ©   (2005-09-29 09:52) [40]

2[39] ANB ©   (29.09.05 09:15)
А откуда ноги растут у твоей озабоченности? С чего бы вдруг юзер стал вводить левые значения и каким образом? Шаловливыми ручками всегда можно вмешаться и на каждый узерский чих заплат не напишешь. ИМХО.


 
ANB ©   (2005-09-29 10:05) [41]


> Sergey13 ©   (29.09.05 09:52) [40]
- не, под клиентом я подразумевал клиентское приложение. Я видел уже несколько решений, но они все не очень универсальны и в каждом есть возможность граблей. Просто сейчас рисую небольшой проектик и на нем хотел бы отработать технологию. Если юзер ручками введет дубль, то, ессно, правильным будет поругаться и послать его.


 
Sergey13 ©   (2005-09-29 10:34) [42]

2[41] ANB ©   (29.09.05 10:05)
>- не, под клиентом я подразумевал клиентское приложение.
Я догадался. 8-)
Потому и спросил. Если в прикладе прописана вставка ИД из сиквенса, как в таблице появятся левые (не от туда) значения? Из "Плюсов" и "Девелоперов"? Так тогда надо безопасностью заниматься, а не сиквенсы "выравнивать" .
ИМХО.


 
ANB ©   (2005-09-29 10:39) [43]


> Sergey13 ©   (29.09.05 10:34) [42]

А если встеблится добавить скриптиком чего-нибудь ? Со связками ? Могу же я себе позволить работать в MS SQL напрямую с автоинкрементарным полем и при этом ничего не ломается ? Плюс пока приклад пишу я, а вот развивать - вовсе не факт.


 
Sergey13 ©   (2005-09-29 11:05) [44]

2 [43] ANB ©   (29.09.05 10:39)
> А если встеблится добавить скриптиком чего-нибудь ? Со связками ?

Скриптик писать надо с учетом этого или чистить за собой, как уже советовалось в [25]. Это, ИМХО, разумнее, нежели (повторяюсь опять же) "лишний код в базе годами крутить"

>Могу же я себе позволить работать в MS SQL напрямую с автоинкрементарным полем и при этом ничего не ломается ?

Про это не знаю, не работал.

>Плюс пока приклад пишу я, а вот развивать - вовсе не факт.

Тогда это будет не твоя проблема. 8-)


 
ANB ©   (2005-09-29 11:47) [45]


> Тогда это будет не твоя проблема. 8-)
- так не солидно. Мне ж за это денежку заплатят. Сверх зарплаты.


 
Fay ©   (2005-09-29 12:21) [46]

2 ANB ©   (27.09.05 15:45) [19]

Обратите внимание на [2]. Sergey13 совершенно прав:
>> select GT_Product_Firm_SQ.Currval
>> может и ошибку дать, если сессия еще не дергала этот сиквенс.

Могу только добавить, что не "может" дать ошибку, а ДАСТ 8)


 
ANB ©   (2005-09-29 12:25) [47]


> Fay ©   (29.09.05 12:21) [46]
- да нарвался уже. Я же постил. Кстати, в НЕКОТОРЫХ случаях может и не дать, но редко. Как раз в моем случае я на нее сразу нарвался. Попробовал заменить на nextval, но обнаружил уже логическую ошибку : если в клиентском приложении я ручками мотаю сиквенс и присваиваю жестко полученный ID. то триггер проматывает его лишний раз.


 
Sergey13 ©   (2005-09-29 12:33) [48]

2ANB ©   (29.09.05 12:25)
Добраться до значения сиквенса ведь можно и через
select * from all_sequences
Может это тебя натолкнет на что полезное?
Хотя я по прежнему считаю, что ты перемудриваешь. 8-)


 
ANB ©   (2005-09-29 12:40) [49]


> Sergey13 ©   (29.09.05 12:33) [48]
- хм. А таки я попробую. Кстати, таки придется втыкать проверку и в Is null. Может кому всеблится отключить триггер, накидать записей, а потом включить. И сиквенс таки не перемотается. Никто не знает, как не напарываться на мутацию при обращении к этой же таблице в триггерре ?


 
Danilka ©   (2005-09-29 12:46) [50]

ANB ©   (29.09.05 12:25)

> Fay ©   (29.09.05 12:21) [46]
- да нарвался уже. Я же постил. Кстати, в НЕКОТОРЫХ случаях может и не дать, но редко. Как раз в моем случае я на нее сразу нарвался. Попробовал заменить на nextval, но обнаружил уже логическую ошибку : если в клиентском приложении я ручками мотаю сиквенс и присваиваю жестко полученный ID. то триггер проматывает его лишний раз.


А зачем тебе его на клиенте дергать?
Пущщай в триггере и дергается, а узнать какое именно значение записалось можео с помощью ретурнинга.


 
Sergey13 ©   (2005-09-29 12:46) [51]

2 [49] ANB ©   (29.09.05 12:40)
А если какому дураку захочется ввести ИД=максимальному значению сиквенса, или около того?


 
Val ©   (2005-09-29 12:49) [52]

>ANB ©
боге мой :(
Q:Как правильно написать триггер для автоприсвоения ID
A:

create or replace trigger GT_Product_PK_TR
before insert on GT_Product
for each row
declare
begin
 select GT_Product_SQ.NextVal into :New.ID from dual;
end GT_Product_PK_TR;

Всё. Автоприсвоение - это _автоприсвоение_ - никаких вставок с заданным id. Проблемы либо надуманы, либо неверно спроектирована логика работы с таблицей.


 
Danilka ©   (2005-09-29 12:53) [53]

Val ©   (29.09.05 12:49)
>ANB ©
боге мой :(
Q:Как правильно написать триггер для автоприсвоения ID
A:

create or replace trigger GT_Product_PK_TR
before insert on GT_Product
for each row
declare
begin
select GT_Product_SQ.NextVal into :New.ID from dual;
end GT_Product_PK_TR;

Всё. Автоприсвоение - это _автоприсвоение_ - никаких вставок с заданным id. Проблемы либо надуманы, либо неверно спроектирована логика работы с таблицей.


ну не совсем так. всетаки лучше проверять на null.
например, вариант когда инфа из нескольких баз сливается в одну.
тогда сиквенс дергать ненадо.
правда, и перематывать его потом тоже ненадо, если заранее предусмотреть такой вариант, и длякаждой базы предусмотреть свой диапазон значений, либо шаг отличный от 1 + начальное смещение для каждой базы.

а вот разрешить юзерам самому задавать ид это по-моему глупо.


 
Sergey13 ©   (2005-09-29 13:03) [54]

2 ANB ©
Вот еще вспомнил. Я однажды делал подобное. Надо было сделать записи с жесткими кодами (типа значения по умолчанию, не важно). Так я просто сделал их отрицательными. И выделяются среди других и сиквенсу не мешают.


 
ANB ©   (2005-09-29 13:12) [55]

Во, вот так я сделал и, вроде, работает :

create sequence Gt_Firm_Sq
minvalue 1
start with 1
increment by 1
nocache
order;
/
create or replace trigger Gt_Firm_Pk_Tr
before insert
on Gt_Firm
for each row
declare
Cur_ID                        number;
begin
if :new.ID is null then
 select Gt_Firm_Sq.nextval
   into :new.ID
   from dual;
else
 select (Us.Last_Number - 1)
   into Cur_ID
   from User_Sequences Us
  where Us.Sequence_Name = upper ("Gt_Firm_Sq");

 while (Cur_ID < :new.ID) loop
  select Gt_Firm_Sq.nextval
    into Cur_ID
    from dual;
 end loop;
end if;
end Gt_Firm_Pk_Tr;
/

Только от выключения/включения не защищает. Но на этот случай пусть уже сами потом сиквенс мотают. Можно при запуске клиента проверять включенность триггеров и соответствие сиквенсна ИД.


 
ANB ©   (2005-09-29 13:13) [56]


> Sergey13 ©   (29.09.05 12:46) [51]
- будет сам себе злостный буратино. К тому же можно это на клиенте проверить. Или в том же триггере.


 
Danilka ©   (2005-09-29 13:14) [57]

Sergey13 ©   (29.09.05 13:03)
2 ANB ©
Вот еще вспомнил. Я однажды делал подобное. Надо было сделать записи с жесткими кодами (типа значения по умолчанию, не важно). Так я просто сделал их отрицательными. И выделяются среди других и сиквенсу не мешают.


А можно сразу сиквенсу сделать шаг двойку, в базе которая для разработки сделать чтоб сиквенс начинался с двойки и спокойно в нее вносить всякие тестовые данные, удалять, а потом спокойно снимать скрипт на то что нужно и переносить в рабочую, ибо в рабочей ид-шники будут все нечетные, а в той - все четные.
:)


 
Danilka ©   (2005-09-29 13:20) [58]

[56] ANB ©   (29.09.05 13:13)


А по-моему это ты сам себе злобный буратино, твоего самого первого варианта всегда хватало в том числе и на базе с тысячью таблиц и нескольких сотен сиквенсов.


 
Курдль ©   (2005-09-29 13:23) [59]


> ANB ©   (29.09.05 10:39) [43]
> Могу же я себе позволить работать в MS SQL напрямую с
> автоинкрементарным полем и при этом ничего не ломается ?


Это что, шутка? :-)  Как это "напрямую"? Т.е. взять и прописать в поле уникального идентификатора что попало? Везет вам, пользователям MS SQL!
А как, например, Вы на клиента можете получить уникальный идентификатор для выбранной таблицы?


 
Sergey13 ©   (2005-09-29 13:24) [60]

2[57] Danilka ©   (29.09.05 13:14)
Можно и так, только у АНБ вроде "задача" (или идея фикс!!! 8-) отказаться иногда от сиквенса и заносить скриптом с прописанными жеско ИД-шниками.


 
Val ©   (2005-09-29 13:26) [61]

эту идею фикс можно оформить в виде хп и для вставки использовать именно ее.


 
ANB ©   (2005-09-29 14:05) [62]


> Курдль ©   (29.09.05 13:23) [59]
- автоикрементальность в MS SQL можно временно отключать и прописывать ID прямо в инсерте. При это счетчик почему все равно мотает. Я не являюсь пользователем MS SQL, посему точно уже не помню, как я это делал. Достать все поля после вставки нельзя, а вот автосгенеренный ID можно.

> Danilka ©   (29.09.05 13:20) [58]
- есть еще варианты, когда на все таблицы используется один сиквенс или в качестве ИД генерится GUID. И все они имеют право на существование.


 
Курдль ©   (2005-09-29 14:30) [63]


> ANB ©   (29.09.05 14:05) [62]
> - автоикрементальность в MS SQL можно временно отключать
> и прописывать ID прямо в инсерте. При это счетчик почему
> все равно мотает. Я не являюсь пользователем MS SQL, посему
> точно уже не помню, как я это делал. Достать все поля после
> вставки нельзя, а вот автосгенеренный ID можно.


Не могу себе представить, зачем может понадобиться "автоикрементальность временно отключать" - это же гнездовье для потенциальных ошибок при многопользовательской работе.

Меня инетерсует не как "получить после", а как "получить до".
Ведь нередко приходится на клиенте в один прием создавать туеву хучу записей во взаимосвязанных таблицах и знать значение первичного (внешнего) ключа заранее.

Напр. в оракле можно отправить запрос select SEQ_NAME.nextval from dual или в сайбэйсе select GetIdentity("TAVLE_NAME") from dummy. В IB тоже есть возможность получить значение генератора (не помню синтаксиса, типа select GEN_ID("GEN_NAME", 1) from rdb$database).
Как это будет выглядеть на MS SQL?


 
Danilka ©   (2005-09-29 14:35) [64]

Курдль ©   (29.09.05 14:30)
Меня инетерсует не как "получить после", а как "получить до".
Ведь нередко приходится на клиенте в один прием создавать туеву хучу записей во взаимосвязанных таблицах и знать значение первичного (внешнего) ключа заранее.


Подскажешь пример такой необходимости?
Всегда идет сначала вставка в мастер-таблицу, а уж затем во все связанные.
А иначе констрейнт просто не даст всавить в подчиненные, когда в мастер-таблице еще нет записи.
Буду премного благодарен, если сможешь переубедить, прям откроешь мне глаза.


 
Danilka ©   (2005-09-29 14:38) [65]

ANB ©   (29.09.05 14:05)
- есть еще варианты, когда на все таблицы используется один сиквенс или в качестве ИД генерится GUID. И все они имеют право на существование.


Кто-бы спорил.
Мне прочто непонятно зачем делать всякие лишние навороты, когда можно во всех случаях обойтись самым первым вариантом.
В том числе и тогда, когда сиквенс один на всех.


 
Курдль ©   (2005-09-29 14:43) [66]


> Danilka ©   (29.09.05 14:35) [64]
> Подскажешь пример такой необходимости?
> Всегда идет сначала вставка в мастер-таблицу, а уж затем
> во все связанные.
> А иначе констрейнт просто не даст всавить в подчиненные,
>  когда в мастер-таблице еще нет записи.
> Буду премного благодарен, если сможешь переубедить, прям
> откроешь мне глаза.


А в чем противоречие с тем, что я написал выше?
На клиенте заполняешь группу датасэтов, например - одну запись в мастер-таблицу, и по нескольку в связанные. Потом, проверив по первичным признакам: DataBase.ApplyUpdates([dsMaster, dsSlave1, dsSlave2...]);
Но для этого надо заранее знать ID следующей записи в мастер-таблице!


 
Danilka ©   (2005-09-29 14:48) [67]

Курдль ©   (29.09.05 14:43)

> Danilka ©   (29.09.05 14:35) [64]
> Подскажешь пример такой необходимости?
> Всегда идет сначала вставка в мастер-таблицу, а уж затем
> во все связанные.
> А иначе констрейнт просто не даст всавить в подчиненные,
>  когда в мастер-таблице еще нет записи.
> Буду премного благодарен, если сможешь переубедить, прям
> откроешь мне глаза.

А в чем противоречие с тем, что я написал выше?
На клиенте заполняешь группу датасэтов, например - одну запись в мастер-таблицу, и по нескольку в связанные. Потом, проверив по первичным признакам: DataBase.ApplyUpdates([dsMaster, dsSlave1, dsSlave2...]);
Но для этого надо заранее знать ID следующей записи в мастер-таблице!


Делаешь на клиенте запись в мастер-таблицу, затем, полученое значение ид (ретурнингом или еще как) прописываешь в детальных таблицах и уже их и апплишь.


 
Danilka ©   (2005-09-29 14:49) [68]

Курдль ©   (29.09.05 14:43)


Хотя твой вариант может быть и проще. Но я так не делал. :)


 
Курдль ©   (2005-09-29 15:02) [69]


> Danilka ©   (29.09.05 14:48) [67]
> Делаешь на клиенте запись в мастер-таблицу, затем, полученое
> значение ид (ретурнингом или еще как) прописываешь в детальных
> таблицах и уже их и апплишь.


"Делаешь на клиенте запись в мастер-таблицу". Т.е. ее записываешь в реальную БД, открыв транзакцию, и держишь ее открытой, пока не набьешь в БД всех зависимых?


 
Val ©   (2005-09-29 15:03) [70]

>[63] Курдль ©   (29.09.05 14:30)

> Меня инетерсует не как "получить после", а как "получить
> до".

Тут суть в разной работе с генераторами и полем-автоинкрементом.
(Все-равно, например, вам не понадобится ид мастер таблицы, полученный заранее, если при вставке в нее получите экзепшн)
При работе с генераторами принято сначала получать будущее значение, потом пытаться вставить, потом проводить вставку в дочерние.
При работе с автоинкрементом принятно делать вставку, получать значение автоинкремента и вставлять в дочерние.
Разница в принципе.


 
Danilka ©   (2005-09-29 15:06) [71]

Курдль ©   (29.09.05 15:02)

> Danilka ©   (29.09.05 14:48) [67]
> Делаешь на клиенте запись в мастер-таблицу, затем, полученое
> значение ид (ретурнингом или еще как) прописываешь в детальных
> таблицах и уже их и апплишь.

"Делаешь на клиенте запись в мастер-таблицу". Т.е. ее записываешь в реальную БД, открыв транзакцию, и держишь ее открытой, пока не набьешь в БД всех зависимых?


Во всех детальных уже все "набито". Все что я описал происходит в одной процедуре после нажатия юзером кнопки "записать".


 
Курдль ©   (2005-09-29 15:09) [72]


> Val ©   (29.09.05 15:03) [70]


При работе с компонентами "DOA", например, идентификатору ставится в соответствие последовательность в дизайн-тайме прямо в инспекторе объектов.
Я, видимо, так и не понял, в чем проблема автора :(


 
Val ©   (2005-09-29 15:11) [73]

думаю, никто не понял :)


 
ANB ©   (2005-09-29 15:40) [74]


> Курдль ©   (29.09.05 15:09) [72]


> Val ©   (29.09.05 15:11) [73]

Чисто принципиально, в таблицы можно писать данные не только из программы - клиента, когда можно просто настроить компоненты (это и в OADC работает и в DOA). И проблема с получением автосгенеренных в триггере значений у меня не стоит, т.к. в оракле есть returning (кстати, в MS SQL есть @identity(если я синтаксис не перепутал)).


 
Val ©   (2005-09-29 15:57) [75]


> И проблема с получением автосгенеренных в триггере значений
> у меня не стоит

что я и говорил ранее. причем невзирая на returning.


 
Курдль ©   (2005-09-29 16:04) [76]


> ANB ©   (29.09.05 15:40) [74]
>
>
> > Курдль ©   (29.09.05 15:09) [72]
>
>
> > Val ©   (29.09.05 15:11) [73]
>
> Чисто принципиально, в таблицы можно писать данные не только
> из программы - клиента, когда можно просто настроить компоненты
> (это и в OADC работает и в DOA). И проблема с получением
> автосгенеренных в триггере значений у меня не стоит, т.к.
>  в оракле есть returning (кстати, в MS SQL есть @identity(если
> я синтаксис не перепутал)).
>


1. Мало кто понял, зачем все эти тибидоханья? :)
Чтобы вручную установить currval последовательности? Так оно и так устанавливается вручную!

2. @@identity есть, но доступен только В МОМЕНТ ИСПОЛНЕНИЯ DML!
Его нельзя вынуть запросом!


 
Fay ©   (2005-09-29 16:10) [77]

2 Курдль ©   (29.09.05 16:04) [76]
>> Его нельзя вынуть запросом!
В каком смысле?


 
Курдль ©   (2005-09-29 16:13) [78]


> Fay ©   (29.09.05 16:10) [77]
> В каком смысле?


Как заранее получить следующее уникальное значение идентификатора определенной таблицы в MS SQL?


 
Danilka ©   (2005-09-29 16:29) [79]

Курдль ©   (29.09.05 16:13)
Как заранее получить следующее уникальное значение идентификатора определенной таблицы в MS SQL?


Я не знаю ниодного примера, когда без этого нельзя было-бы обойтись.
Собственно, именно такой пример от тебя я и хотел услышать.
Ты привел пример, когда все равно обойтись можно другими способами, я просто думал, что есть что-то еще, более непреодолимое. :)


 
ANB ©   (2005-09-29 16:38) [80]


> Курдль ©   (29.09.05 16:13) [78]


> Как заранее получить следующее уникальное значение идентификатора
> определенной таблицы в MS SQL?

- а зачем ?
Открываем транзакцию
Инсертим в мастер-таблицу
Узнаем ID добавленной записи
Инсертим в подчиненные таблицы
Коммитим.



Страницы: 1 2 3 вся ветка

Форум: "Базы";
Текущий архив: 2005.11.13;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.64 MB
Время: 0.042 c
1-1130228385
Vriter
2005-10-25 12:19
2005.11.13
Расширение CheckListBox


3-1128394079
npr2
2005-10-04 06:47
2005.11.13
Запись картинки с Image в БД Access


1-1130300515
MikeGipson
2005-10-26 08:21
2005.11.13
Не шевелится поток в ХР


14-1129904509
Tesla
2005-10-21 18:21
2005.11.13
Посоветуйте компонент


14-1129889736
dr Tr0jan
2005-10-21 14:15
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
Английский Французский Немецкий Итальянский Португальский Русский Испанский