在oracle中将另一个表中的字段用作具有类型CONSTRAINT的最大行数
我有两张桌子:在oracle中将另一个表中的字段用作具有类型CONSTRAINT的最大行数,oracle,Oracle,我有两张桌子: CREATE TABLE users ( user_id INT(7) NOT NULL, restricted_type VARCHAR(64) NOT NULL ) 我想在insert上检查一下,使用restricted\u type=type\u restriction.name的限制用户不超过个 此时,我正在使用此查询插入数据: INSERT INTO users (user_id, restricted_type) SELECT <
CREATE TABLE users (
user_id INT(7) NOT NULL,
restricted_type VARCHAR(64) NOT NULL
)
我想在insert上检查一下,使用restricted\u type=type\u restriction.name的限制用户不超过个
此时,我正在使用此查询插入数据:
INSERT INTO users (user_id, restricted_type) SELECT <id>, <type> FROM DUAL
WHERE NOT EXISTS (
SELECT 1
FROM type_restrictions T
WHERE T.name = <type> AND T.restriction < (
SELECT COUNT(*)
FROM users U
WHERE U.user_id = <id> AND U.restricted_type = <type>)
)
但是,如果有两个或多个并行查询,那么最终可能会有更多用户使用受限类型而不是此类型的实际限制
有没有办法让这种约束起作用?另外,我总是在每个查询中只插入一行,如果有帮助的话,您不能使用select。。。拘束地。无法从正常触发器中插入的表中进行选择。你能做什么?物化视图可能,我不确定或复合触发器。以下是我的工作尝试:
create or replace trigger trg_users_restrict
for insert on users compound trigger
type tt is table of number index by varchar2(5);
vt tt;
i varchar2(5);
v_max int;
before statement is
begin
for r in (select restricted_type, count(1) cnt from users group by restricted_type)
loop
vt(r.restricted_type) := r.cnt;
end loop;
end before statement;
after each row is
begin
begin
vt(:new.restricted_type) := vt(:new.restricted_type) + 1;
exception when no_data_found then
vt(:new.restricted_type) := 1;
end;
end after each row;
after statement is
begin
i := vt.first;
while i is not null loop
select nvl(max(restriction), 0) into v_max
from type_restrictions where name = i;
if vt(i) > v_max then
raise_application_error( -20001,
'maximum number exceeded for restriction type ' || i );
end if;
i := vt.next(i);
end loop;
end after statement;
end trg_users_restrict;
在before语句中,我将users表中的数据分组到集合中。在每行之后,我在集合中为新插入的行增加适当的值。在after语句中,我检查集合中的数据是否超出表类型限制中允许的范围
当两个会话插入concurent数据时,这将导致异常。您可以尝试将该逻辑放入触发器中,如果一行违反该规则,则会引发错误。我已尝试将逻辑完全放入插入触发器之前不存在的位置,但问题仍然存在。。对于两个或多个并行事务,我有时会违反限制,但触发器对此保持沉默。我会再试一次,以防万一。
create or replace trigger trg_users_restrict
for insert on users compound trigger
type tt is table of number index by varchar2(5);
vt tt;
i varchar2(5);
v_max int;
before statement is
begin
for r in (select restricted_type, count(1) cnt from users group by restricted_type)
loop
vt(r.restricted_type) := r.cnt;
end loop;
end before statement;
after each row is
begin
begin
vt(:new.restricted_type) := vt(:new.restricted_type) + 1;
exception when no_data_found then
vt(:new.restricted_type) := 1;
end;
end after each row;
after statement is
begin
i := vt.first;
while i is not null loop
select nvl(max(restriction), 0) into v_max
from type_restrictions where name = i;
if vt(i) > v_max then
raise_application_error( -20001,
'maximum number exceeded for restriction type ' || i );
end if;
i := vt.next(i);
end loop;
end after statement;
end trg_users_restrict;