触发唯一对约束

时间:2014-09-20 22:20:03

标签: sql database oracle triggers

我正在尝试创建一个触发器,使其像一个异常,不会在数据集中插入或更新两次无序对。

例如,假设集合{A,B},其中A和B都是主键列,表中存在{A,B},我不希望允许集合{B,A}存在因为该关系已经用{A,B}定义。

以下是我的尝试,但它提供了Trigger created with compilation errors.,而且我也看不到如何针对newold信息执行此操作。

CREATE TRIGGER pair
BEFORE INSERT OR UPDATE ON pairing
DECLARE exists_pair NUMBER;

BEGIN
    SELECT MAX(COUNT_VAL) INTO exist_pair
    FROM (SELECT COUNT(*) FROM pairing p, pairing p2 WHERE p2.element_one = p.element_two AND p.element_one  = p2.element_two)

    IF exist_pair > 0 THEN
        RAISE SOME_EXCEPTION;
    END IF;
END;

显然这不是我想要的,但它提出了一个想法。这将改为每次返回0,直到输入错误,然后它会说每个有效或无效的条目都是无效的......所以它不是我想要的但我不知道如何使用:new:old在这种情况下。

这必须适用于oracle。

这是一个带有示例插入的SQLfiddle,它应该失败: http://sqlfiddle.com/#!4/1afb7/1/0

3 个答案:

答案 0 :(得分:5)

基于功能的索引将起作用:

create unique index unique_pair_ix on pairing (least(element_one,element_two),greatest(element_one,element_two));

顺便说一句:使用行触发器从同一个表中进行选择将导致:

ORA-04091: table XXXX is mutating, trigger/function may not see it

如果您尝试在单个语句中插入或更新多行。所以你不能使用:OLD和:NEW。

答案 1 :(得分:2)

  

例如,假设集合{A,B},其中A和B都是主键列,表中存在{A,B},我不希望允许集合{B,A}存在因为该关系已经用{A,B}定义。

强制唯一性的最直接方法是添加唯一索引。但是“简单”索引不起作用:

-- This does not help here
CREATE UNIQUE INDEX sample_uniq_ab_fn ON SAMPLE (B,A);

假设PRIMARY KEY(A,B),使用此设置,在插入(A=1,B=2)时,您只需在主键索引中强制(1,2)的唯一性和 {的唯一性{1}}在我的唯一索引中。这不会阻止在主键索引中插入(2,1) (A=2,B=1) 而不是。唯一索引中也不(2,1)


在这里,您需要function based index,因为您希望(min(a,b),max(a,b))是唯一的。这样的事情:

(1,2)

答案 2 :(得分:0)

为了彻底,我会发布我的答案,我最终通过触发器结束了,但它确实遭受了错误

ORA-04091: table XXXX is mutating, trigger/function may not see it

CREATE OR REPLACE TRIGGER pair 
BEFORE INSERT ON pairing
FOR EACH ROW
DECLARE
    found_count number;
BEGIN
    SELECT COUNT(1) INTO found_count FROM pairing 
    WHERE (element_1=:new.element_2 AND element_2=:new.element_1);
    IF found_count = 1 THEN
        RAISE_APPLICATION_ERROR(-20001, 'The pairing already exists');
    END IF;
END;
.
RUN; 

我必须注意,您必须在sqlplus中运行show errors才能在显示Trigger created with compilation errors.

时真正看到触发器中的错误