Главная страница
    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)
А откуда ноги растут у твоей озабоченности? С чего бы вдруг юзер стал вводить левые значения и каким образом? Шаловливыми ручками всегда можно вмешаться и на каждый узерский чих заплат не напишешь. ИМХО.


 
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 добавленной записи
Инсертим в подчиненные таблицы
Коммитим.


 
Fay ©   (2005-09-29 16:38) [81]

2 Курдль ©   (29.09.05 16:13) [78]
>> Как заранее получить следующее уникальное значение
>> идентификатора определенной таблицы в MS SQL?
Никак, но как это связано с "в оракле есть returning" ?

2 Danilka ©   (29.09.05 16:29) [79]
на самом деле, таких примеров можно встретить произвольное количество.
Моему любимому MSSQL действительно очень не хватает тригеров before и генераторов (которые не зависят от транзакций).


 
ANB ©   (2005-09-29 16:40) [82]


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


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


> Собственно, именно такой пример от тебя я и хотел услышать.


Автор писал про оракл:


> ANB ©   (27.09.05 15:38) [16]
> 1. Отмечал оракл, но так как на форуме бага, то написал
> еще и в скобках тип БД.


Как получить ID заранее с 3-х СУБД я привел в [63]! А вот как это сделать в MS SQL - я не знаю! Но чую, что кто-то знает! :)  То ли SCOPE_IDENTITY, то ли нечто похожее!


 
ANB ©   (2005-09-29 16:42) [84]


> Моему любимому MSSQL действительно очень не хватает тригеров
> before
- хоть я MS SQL и не люблю, но вот логика триггеров мне там больше понравилась. Во всяком случае, мутаций таблиц там не бывает.


 
Fay ©   (2005-09-29 16:43) [85]

2 ANB ©   (29.09.05 16:40) [82]
Такое "можно" называется "нельзя".


 
ANB ©   (2005-09-29 16:45) [86]


> Курдль ©   (29.09.05 16:41) [83]
- ты можешь получить только текущее значение. Следующее же - это + 1, но так делать не кузяво, так как есть вероятность, что пользователь нарвется на дубль при синхронной работе. Это будет тоже самое, что Max(ID) + 1. Т.е. никакого смысла.
А зачем его получать до ? Плюс, ходят слухи, что таки в следующей версии генераторы появятся.


 
Fay ©   (2005-09-29 16:46) [87]

2 Курдль ©   (29.09.05 16:41) [83]
>> То ли SCOPE_IDENTITY, то ли нечто похожее!
Ни в коем случае!!


 
ANB ©   (2005-09-29 16:46) [88]


> Fay ©   (29.09.05 16:43) [85]
> 2 ANB ©   (29.09.05 16:40) [82]
> Такое "можно" называется "нельзя".
- Гы, гы. Но время от времени на форуме появляются вопросы - как это сделать.


 
Val ©   (2005-09-29 16:46) [89]

потому что не обращаются к таблице в триггере перед вставкой :)


 
Fay ©   (2005-09-29 16:47) [90]

2 ANB ©   (29.09.05 16:45) [86]
>>  в следующей версии генераторы появятся
В MSSQL 2015? 8)


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


> - хоть я MS SQL и не люблю, но вот логика триггеров мне
> там больше понравилась. Во всяком случае, мутаций таблиц
> там не бывает.


Мутаций не бывает, т.к. он блокировщик, а не версионник! :)

> ANB ©   (29.09.05 16:45) [86]
> А зачем его получать до ? Плюс, ходят слухи, что таки в
> следующей версии генераторы появятся.


Я писал, зачем получать "до" в [66].
Чтобы заполнить максимум данных на клиенте, не держа при этом транзакцию открытой. Это корпоративный стандарт! Никаких "прокруток", никаких "max(ID)" и т.п. Только заранее получить, и пользовать.


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


> Fay ©   (29.09.05 16:46) [87]
>
> 2 Курдль ©   (29.09.05 16:41) [83]
> >> То ли SCOPE_IDENTITY, то ли нечто похожее!
> Ни в коем случае!!


А чего тогда молчат все апологеты MS SQL? 8-()
Это ж полная Ж! :-(


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


> Я писал, зачем получать "до" в [66].
> Чтобы заполнить максимум данных на клиенте

Хм. Странно. Была у меня раз задачка, где я заполнял на клиенте настроечную таблицу, а потом пересылал пачку записей за одну транзакцию. Но мне не пришлось заранее доставать ID. Это некошерный подход, доставать ID до того, как юзер нажмет кнопку ОК.


 
Fay ©   (2005-09-29 16:57) [94]

2 Курдль ©   (29.09.05 16:53) [92]

Есть причины, которые позволяют мириться с некоторыми недостатками.
Пожалуй главная (но не единственная, конечно) из них - оптимизатор MSSQL (vs Oracle vs FB).


 
ANB ©   (2005-09-29 16:57) [95]


> Курдль ©   (29.09.05 16:53) [92]
- лучше не ругайся, а изучай грабли. От сумы и работы с MS SQL ни один программист не застрахован :)))


 
ANB ©   (2005-09-29 16:58) [96]


> Есть причины, которые позволяют мириться с некоторыми недостатками.
>
> Пожалуй главная (но не единственная, конечно) из них - оптимизатор
> MSSQL (vs Oracle vs FB).
???


 
Fay ©   (2005-09-29 16:59) [97]

2 ANB ©   (29.09.05 16:56) [93]
1) А почему, собственно, "до" ?
2) GUID-ы экономить не пробовали ? 8)


 
Fay ©   (2005-09-29 17:00) [98]

2 ANB ©   (29.09.05 16:58) [96]
>> ???
!!!


 
Курдль ©   (2005-09-29 17:03) [99]


> ANB ©   (29.09.05 16:57) [95]
> - лучше не ругайся, а изучай грабли. От сумы и работы с
> MS SQL ни один программист не застрахован :)))


Честно говоря, я уже второй год, как перешел в основных проектах на вижуал кролика. Так что эти проблемы совсем канули в лету. Ведь в ADO.NET о таких мелочах, как ID вообще не задумываешься: набил датасэт связанными таблицами  и сбросил в базу. Он сам разрулит, кому-что подставить.


 
kesha ©   (2005-09-29 18:25) [100]


> Курдль ©   (29.09.05 17:03) [99]


a esli sna4ala sochranil na lokal PK, a 4eres 2 dnja sbrosil v global DB


 
Fay ©   (2005-09-29 19:17) [101]

2 kesha ©   (29.09.05 18:25) [100]

Хоть через а года


 
Fay ©   (2005-09-29 19:18) [102]

B cmbIcJIE, "XOTb 4EPE3 DBA rODa" 8)


 
ANB ©   (2005-09-30 09:27) [103]


> Fay ©   (29.09.05 17:00) [98]
> 2 ANB ©   (29.09.05 16:58) [96]
> >> ???
> !!!
- чем оптимизатор MS SQL лучше ораклового ?


 
Sergey13 ©   (2005-09-30 09:31) [104]

Ну и бодягу вы тут развели. Даже для потрепаловки приличный объем.
А щас еще и холивар начнется.
8-)


 
ANB ©   (2005-09-30 10:03) [105]


> Sergey13 ©   (30.09.05 09:31) [104]
- а всего то просил посмотреть триггер.


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


> kesha ©   (29.09.05 18:25) [100]
> a esli sna4ala sochranil na lokal PK, a 4eres 2 dnja sbrosil  v global DB


Я не понял, это вопрос? И в чем его суть?
Если просто держать заполненный датасэт (напоминаю - не TDataSet из Delphi, а System.Data.DataSet из ADO.NET, - для особо любознательных), который содержит в себе несколько таблиц со связанными данными, релэйшны и констрэйнты, - то ничего с ним не случится. Все "автоинкрементные" идентификаторы, внешние ключи и т.п. заполняются фиктивными данными (напр. для integer рекомендованы -1, -2, -3...). А в момент исполнения метода Update объекта DataAdapter, все они преобразуются в реальные значения из генераторов, последовательностей и т.п.

Если же Вас интересует, как сохранить данные из такого датасэта на 2 дня, чтобы потом их вставить в БД - есть метод DataSet.WriteXml(string filename);
который сохранит весть датасэт в XML, сохранив всю иерархию данных.


 
kesha ©   (2005-09-30 10:34) [107]


> Курдль ©   (30.09.05 10:14) [106]


Spasibo, potom obdumau.


 
Danilka ©   (2005-09-30 10:53) [108]

[81] Fay ©   (29.09.05 16:38)
Примеров полезности генераторов/сиквенсов не привязанных к конкретной таблице, таки да, согласен, можно найти.
Триггеры before тоже полезны бывают.
А вот именно необходимость знать значение ид таблицы до инсерта я не могу придумать.

[106] Курдль ©   (30.09.05 10:14)
То-есть, фактически ADO.NET делает то-же самое, что я написал в [67].


 
Курдль ©   (2005-09-30 11:10) [109]


> Danilka ©   (30.09.05 10:53) [108]

Не согласен по всем 3-м пунктам!

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

Если в БД хотят сделать общий идентификатор для разных таблиц, производят процесс наследования "inherit" от материнской таблицы. Если на одну запись в материнской таблице не могут ссылаться 2 записи в дочерних - взводят свойство  наследования "mutually exclusive".

Пользу получения значения ID до исполнения DML я уже неоднократно приводил - чтобы заполнять связанные таблицы и при этом не держать транзакцию открытой (это важно при многопользовательском режиме).

ADO.NET не делает то-же самое, что ты написал в [67]. Но делает это на самом низком интерфейсном уровне и гарантирует от ошибок прикладного программирования.


 
ANB ©   (2005-09-30 11:58) [110]


> Пользу получения значения ID до исполнения DML я уже неоднократно
> приводил - чтобы заполнять связанные таблицы и при этом
> не держать транзакцию открытой (это важно при многопользовательском
> режиме).
- а кто мешает заполнение связанных таблиц проводить быстро в одной транзакции, получив мастер ID после вставки ? Или вообще засунуть все это в один DML ?

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



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

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

Наверх




Память: 0.77 MB
Время: 0.043 c
1-1129882552
kyn66
2005-10-21 12:15
2005.11.13
Как обратиться к выделенной строке ListView?


2-1130307997
vit74
2005-10-26 10:26
2005.11.13
при выполнении приложения выскакивает ошибка


3-1128417033
Ram
2005-10-04 13:10
2005.11.13
Как реализовать модификацию базы через запрос SQL?


4-1125936978
Still Swamp
2005-09-05 20:16
2005.11.13
Как сменить пароль для пользователя


2-1129779847
Alex77777
2005-10-20 07:44
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
Английский Французский Немецкий Итальянский Португальский Русский Испанский