У меня есть небольшой столик, глядя, как этотTrigger избежать мутирует таблицы и обновление: new.values
table People
( name VARCHAR(20) PRIMARY KEY
,group NUMBER(4)
);
И мне нужно, чтобы создать триггер (или триггеры) Thats позволит ниже правила работы:
- 1 если есть более 10 имена в группе Мне нужно поднять сообщение об ошибке, если кто-то пытается ВСТАВИТЬ следующих людей для этой группы.
- 2, если ВСТАВИТЬ приходит со значением NULL для группы поля мне нужно назначить его группу, которая меньше количества затем 10.
- 3, если есть 10 имен во всех группах я необходимо сгенерировать следующими группа номер.
- 4 Мне нужно избегать мутирующий стол ошибка.
Это то, что я сделал до сих пор:
CREATE OR REPLACE TRIGGER people_bis
BEFORE INSERT ON people
FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
g_count NUMBER(4);
g_num NUMBER(4);
g_l NUMBER(4);
g_r NUMBER(4);
BEGIN
Select count(*) into g_count from people where group = :new.group;
If g_count > 9 Then
raise_application_error (-20003,'Group reached it limit, please choose other');
End if;
If :NEW.group = '' or :NEW.group is null Then
select count (*) into g_l from (select count(imie),group from people group by group having count(name) = 10);
select count (distinct group) into g_r from people;
if g_l = g_r then
select max(group)+1 into g_num from people;
else
select group into g_num from(select group, count(name) from people having count(name) < 10 group by group order by count(group) desc) where rownum < 2;
End if;
:New.group := g_num;
End if;
End people_bis;
Код выше работ, но когда я вставляю, как выбрать из таблицы зеркала, например,
INSERT INTO people(name) select concat(name,'_next') from people_mirror;
В результате оно превышает заданный предел (10) для группы. Также я знаю, что использование PRAGMA AUTONOMOUS_TRANSACTION не лучший способ избежать ошибки в изменении таблицы, и я знаю, что могу достичь этой функциональности, если бы я разделил триггер строки в триггеры операторов, но я просто не понимаю, как это получить ,
Так кто-нибудь? ;)
Заранее спасибо.
------------------- EDIT ------------------------
Это триггеры, которые работают, но все же у меня есть сомнения относительно них, поскольку оба они являются ПЕРЕД и строковыми типами.
CREATE OR REPLACE TRIGGER people_bir1
BEFORE INSERT on people
FOR EACH ROW
DECLARE
V_count NUMBER(2);
BEGIN
If :NEW.group = '' or :NEW.group is null then
return;
end if;
insert into groups values(:New.group,1);
exception when dup_val_on_index then
Select count into v_count from groups where group = :New.group;
UPDATE groups set count = v_count+1 where group = :New.group;
END people_bir1;
CREATE OR REPLACE TRIGGER people_bir2
BEFORE INSERT on people
FOR EACH ROW
DECLARE
g_count NUMBER(2);
g_num NUMBER(2);
begin
if :NEW.group = '' or :NEW.group is null Then
select min(count) into g_count from groups;
if g_count = 10 Then
select max(group) into g_num from groups;
g_num := g_num+1;
Else
select min(group) into g_num from group where count = g_count;
End if;
:New.group := g_num;
Else
select count into g_count from groups where group=:New.group;
if g_count > 9 then
raise_application_error (-20003,'More then 10 people in group please select another');
end if;
end if;
end people_bir2;
, поскольку он слишком длинный, я не мог вставить его в качестве комментария к ответу @TonyAndrews.
Так что я смог разбить его на два триггера, используя дополнительную таблицу 'группы таблиц (группа NUMBER (4) PRIMARY KEY, count NUMBER (2)' и два триггера, но оба они до триггеров строк. работает, но у меня есть сомнения, что использование двух перед триггерами - это правильное решение. Я присоединяю их как ответ ниже. Пожалуйста, взгляните, можете ли вы, чтобы исправить меня. – plomien
новая версия включена в вопрос под маркой EDIT. – plomien