Форум: "Базы";
Текущий архив: 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.04 c