两个具有反向方向的数据库列的唯一约束
Unique constraint on two database columns with reverse direction
我遇到了以下问题:假设我有一个与自身有关系的 table:
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');
意思是table ITEM_RELATION
定义了这个连接的方向,应该不允许添加反向关系。
是否可以使用 Oracle DB?
您可以使用唯一索引来做到这一点。在 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);
但是,这需要按特定顺序插入项目。
我遇到了以下问题:假设我有一个与自身有关系的 table:
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');
意思是table ITEM_RELATION
定义了这个连接的方向,应该不允许添加反向关系。
是否可以使用 Oracle DB?
您可以使用唯一索引来做到这一点。在 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);
但是,这需要按特定顺序插入项目。