こんな感じの小さなテーブルがあります
table People
( name VARCHAR(20) PRIMARY KEY
,group NUMBER(4)
);
そして、以下のルールが機能するようにするトリガー (またはトリガー) を作成する必要が
あります。
- 2 INSERT にグループフィールドの 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 すると
INSERT INTO people(name) select concat(name,'_next') from people_mirror;
、グループに指定された制限 (10) を超えます。また、PRAGMA AUTONOMOUS_TRANSACTIONを使用することは、テーブルの変更エラーを回避するための最良の方法ではないことを知っています。行トリガーをステートメントトリガーに分割すると、この機能に到達できることはわかっていますが、それを取得する方法がわかりません。
それで誰か?;)
前もって感謝します。
- - - - - - - - - -編集 - - - - - - - - - - - -
これらは機能するトリガーですが、どちらも BEFORE と行タイプであるため、まだ疑問があります。
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 の回答にコメントとして貼り付けることができませんでした。