限制值在 table oracle sql 中出现的次数
Limit number of occurrences of value in a table oracle sql
我有oracle sql table 同学,同学都分到组了。
我必须设置限制,所以一个组中的学生不超过 10 个(理想情况下一个组中不超过 N 个学生)。
基本上限制 table 具有相同 GROUP_ID 值的 N 行以上。
这里是table声明。
CREATE TABLE "students"
( "STUDENT_ID" NUMBER(6,0),
"GROUP_ID" NUMBER(6,0),
"FULL_NAME" VARCHAR2(40),
CONSTRAINT "student_id_PK" PRIMARY KEY ("STUDENT_ID")
USING INDEX ENABLE
)
/
ALTER TABLE "students" ADD FOREIGN KEY ("GROUP_ID")
REFERENCES "groups" ("GROUP_ID") ENABLE
/
CREATE TABLE "groups"
( "GROUP_ID" NUMBER(6,0),
"NAME" VARCHAR2(40),
CONSTRAINT "group_id_PK" PRIMARY KEY ("GROUP_ID")
USING INDEX ENABLE
)
/
我尝试使用触发器,当一个组中有超过 10 个学生时会抛出错误。它适用于插入,但对 table 的更新毫无用处,因为我不断得到 error ORA-04091: table students is mutating
这里是触发器的简化版本:
SELECT count(*) INTO stud_in_g
FROM "students"
WHERE GROUP_ID = :NEW.GROUP_ID;
IF stud_in_g>10 THEN
raise_application_error(-20001, 'to many students');
END IF;
我读到 oracle 在更新时禁止从 table 读取。如果是这样,那我怎么保证一个组不能超过10个学生呢?
触发器的“简化版本”没有显示它是什么类型的触发器 - 很可能是行级触发器。由于变异 table 触发器错误,这将不起作用。语句级触发器确实有效:
create table test_table (
id number generated by default on null as identity
constraint test_table_id_pk primary key,
name varchar2(100 char),
the_group varchar2(100 char)
);
Table TEST_TABLE created.
BEGIN
insert into test_table (name, the_group ) values ('Chandler', 'A');
insert into test_table (name, the_group ) values ('Ross', 'A');
insert into test_table (name, the_group ) values ('Joey', 'A');
insert into test_table (name, the_group ) values ('Phoebe', 'B');
insert into test_table (name, the_group ) values ('Jennifer', 'B');
insert into test_table (name, the_group ) values ('Monica', 'B');
commit;
END;
/
PL/SQL procedure successfully completed.
CREATE OR REPLACE TRIGGER test_table_as
AFTER UPDATE OR INSERT ON test_table
DECLARE
l_max_members NUMBER := 3;
BEGIN
FOR r IN (SELECT
the_group,
COUNT(*) AS cnt
FROM
test_table
GROUP BY
the_group
HAVING
COUNT(*) > l_max_members)
LOOP
IF r.cnt > l_max_members THEN
raise_application_error(-20100,'Max '||l_max_members||' per group');
END IF;
END LOOP;
END;
/
Trigger TEST_TABLE_AS compiled
insert into test_table (name, the_group ) values ('Jill', 'B');
Error starting at line : 39 in command -
insert into test_table (name, the_group ) values ('Jill', 'B')
Error report -
ORA-20100: Max 3 per group
ORA-06512: at "KOEN.TEST_TABLE_AS", line 8
ORA-06512: at "KOEN.TEST_TABLE_AS", line 8
ORA-04088: error during execution of trigger 'KOEN.TEST_TABLE_AS'
我有oracle sql table 同学,同学都分到组了。
我必须设置限制,所以一个组中的学生不超过 10 个(理想情况下一个组中不超过 N 个学生)。
基本上限制 table 具有相同 GROUP_ID 值的 N 行以上。
这里是table声明。
CREATE TABLE "students"
( "STUDENT_ID" NUMBER(6,0),
"GROUP_ID" NUMBER(6,0),
"FULL_NAME" VARCHAR2(40),
CONSTRAINT "student_id_PK" PRIMARY KEY ("STUDENT_ID")
USING INDEX ENABLE
)
/
ALTER TABLE "students" ADD FOREIGN KEY ("GROUP_ID")
REFERENCES "groups" ("GROUP_ID") ENABLE
/
CREATE TABLE "groups"
( "GROUP_ID" NUMBER(6,0),
"NAME" VARCHAR2(40),
CONSTRAINT "group_id_PK" PRIMARY KEY ("GROUP_ID")
USING INDEX ENABLE
)
/
我尝试使用触发器,当一个组中有超过 10 个学生时会抛出错误。它适用于插入,但对 table 的更新毫无用处,因为我不断得到 error ORA-04091: table students is mutating
这里是触发器的简化版本:
SELECT count(*) INTO stud_in_g
FROM "students"
WHERE GROUP_ID = :NEW.GROUP_ID;
IF stud_in_g>10 THEN
raise_application_error(-20001, 'to many students');
END IF;
我读到 oracle 在更新时禁止从 table 读取。如果是这样,那我怎么保证一个组不能超过10个学生呢?
触发器的“简化版本”没有显示它是什么类型的触发器 - 很可能是行级触发器。由于变异 table 触发器错误,这将不起作用。语句级触发器确实有效:
create table test_table (
id number generated by default on null as identity
constraint test_table_id_pk primary key,
name varchar2(100 char),
the_group varchar2(100 char)
);
Table TEST_TABLE created.
BEGIN
insert into test_table (name, the_group ) values ('Chandler', 'A');
insert into test_table (name, the_group ) values ('Ross', 'A');
insert into test_table (name, the_group ) values ('Joey', 'A');
insert into test_table (name, the_group ) values ('Phoebe', 'B');
insert into test_table (name, the_group ) values ('Jennifer', 'B');
insert into test_table (name, the_group ) values ('Monica', 'B');
commit;
END;
/
PL/SQL procedure successfully completed.
CREATE OR REPLACE TRIGGER test_table_as
AFTER UPDATE OR INSERT ON test_table
DECLARE
l_max_members NUMBER := 3;
BEGIN
FOR r IN (SELECT
the_group,
COUNT(*) AS cnt
FROM
test_table
GROUP BY
the_group
HAVING
COUNT(*) > l_max_members)
LOOP
IF r.cnt > l_max_members THEN
raise_application_error(-20100,'Max '||l_max_members||' per group');
END IF;
END LOOP;
END;
/
Trigger TEST_TABLE_AS compiled
insert into test_table (name, the_group ) values ('Jill', 'B');
Error starting at line : 39 in command -
insert into test_table (name, the_group ) values ('Jill', 'B')
Error report -
ORA-20100: Max 3 per group
ORA-06512: at "KOEN.TEST_TABLE_AS", line 8
ORA-06512: at "KOEN.TEST_TABLE_AS", line 8
ORA-04088: error during execution of trigger 'KOEN.TEST_TABLE_AS'