具有反向的两个数据库列的唯一约束

时间:2017-07-04 13:59:49

标签: sql database oracle unique-constraint oracledb

我遇到了以下问题:假设我有一张与自身有关系的表:

CREATE TABLE ITEM (
    ID NUMBER(18) PRIMARY KEY,
    NAME VARCHAR2(100 CHAR) NOT NULL
);

ALTER TABLE ITEM ADD CONSTRAINT PK_ITEM PRIMARY KEY (ID);

CREATE TABLE ITEM_RELATION (
    FIRST_ITEM_ID NUMBER(18) NOT NULL,
    SECOND_ITEM_ID NUMBER(18) NOT NULL,
    RELATION_TYPE VARCHAR2(1) NOT NULL
);

ALTER TABLE ITEM_RELATION ADD CONSTRAINT PK_ITEM_RELATION PRIMARY KEY (FIRST_ITEM_ID, SECOND_ITEM_ID, RELATION_TYPE);
--ALTER TABLE ITEM_RELATION ADD CONSTRAINT UK_ITEMS UNIQUE (FIRST_ITEM_ID, SECOND_ITEM_ID, RELATION_TYPE);
ALTER TABLE ITEM_RELATION ADD CONSTRAINT FK_FIRST_ITEM FOREIGN KEY (FIRST_ITEM_ID) REFERENCES ITEM(ID);
ALTER TABLE ITEM_RELATION ADD CONSTRAINT FK_SECOND_ITEM FOREIGN KEY (SECOND_ITEM_ID) REFERENCES ITEM(ID);

现在让我们说,我不认为这种关系是方向性的,即如果第1项与某种类型的第2项有关系,则第2项与第1项的关系不应该相同。

即,不应允许以下内容:

INSERT INTO ITEM (ID, NAME) VALUES (1, 'Item 1');
INSERT INTO ITEM (ID, NAME) VALUES (2, 'Item 2');
INSERT INTO ITEM_RELATION(FIRST_ITEM_ID, SECOND_ITEM_ID, RELATION_TYPE) VALUES (1, 2, 'R');
INSERT INTO ITEM_RELATION(FIRST_ITEM_ID, SECOND_ITEM_ID, RELATION_TYPE) VALUES (2, 1, 'R');

这意味着表ITEM_RELATION定义了此连接的方向,不应该允许它添加反向关系。

是否可以使用Oracle DB?

1 个答案:

答案 0 :(得分:3)

您可以使用唯一索引执行此操作。在Oracle中,您可以使用索引中的函数,因此这将起作用:

create unique index unq_item_relation_3 on
     item_relation(RELATION_TYPE ,
                   least(FIRST_ITEM_ID, SECOND_ITEM_ID),
                   greatest(FIRST_ITEM_ID, SECOND_ITEM_ID)
                  );

通过要求check小于FIRST_ITEM_ID,您可以获得与SECOND_ITEM_ID约束相同的效果:

alter table item_relation add constraint chk_item_relation_2
    check ((FIRST_ITEM_ID < SECOND_ITEM_ID);

但是,这要求按特定顺序插入项目。