是否可以使用“NOT IN”逻辑创建外键约束

时间:2014-01-13 18:45:51

标签: sql oracle foreign-keys foreign-key-relationship

是否可以在表上添加外键约束,这将允许另一个表中不存在的值?

在下面的示例中,两个表都包含USER_ID字段。约束是客户和员工不能具有相同的USER_ID值。

我非常有限地添加新表或以任何方式更改其中一个表。

CUSTOMER
--------------------------
USER_ID     varchar2(10)

EMPLOYEE
--------------------------
USER_ID     varchar2(10)

我想到了一些解决方法,例如包含两个表中的数据或在我可以修改的表上添加插入触发器的视图。

2 个答案:

答案 0 :(得分:1)

不,不存在这样的事情,虽然可以假装。

如果您想以关系方式执行此操作(这比视图/触发器要好得多),则可以选择向所有员工ID添加E,为所有客户ID添加C。但是,如果您有其他属性并且您想确保他们不是同一个人(即您不仅仅对ID感兴趣),这将无效。

如果是这种情况你需要创建第三个表,我们称之为PEOPLE:

create table people ( 
   user_id varchar2(10) not null
 , user_type varchar2(1) not null
 , constraint pk_people primary key (user_id)
 , constraint chk_people_user_types check ( user_type in ('C','E') )
   );
在检查约束中,

C代表客户,E代表员工。然后,您需要在PEOPLE上创建一个唯一的索引/约束:

create index ui_people_id_type on people ( user_id, user_type );

就个人而言,我会在这里停下来,完全放弃你的CUSTOMER和EMPLOYEE表;他们不再有任何用处,你的问题已经解决了。

如果您无法添加新的列/表,则需要与执行此操作的人员交谈并说服他们进行更改。过度复杂的事情只会导致逻辑和混乱的错误(相信我 - 使用视图意味着你需要很多触发器来维护你的表,你必须确保有人只更新视图)。即使花费的时间更长,也能更容易地做好事情。


但是,如果您真的想继续更改CUSTOMER和EMPLOYEE表以包含其USER_TYPE,并确保表中的每一行始终相同,即:

alter table customers add user_type default 'C' not null;
alter table customers add constraint chk_customers_type
      check ( user_type is not null and user_type = 'C' );

答案 1 :(得分:0)

除非您愿意像其他人所建议的那样更改数据模型,否则在保持互斥的同时继续使用现有结构的最简单方法是对两个表的user_ids发出检查约束,以便它们仅验证互斥系列。

例如,您可以发出检查以确保只向客户分配偶数,为员工分配奇数(反之亦然)。

或者,由于两个ID都是varchar,因此使用您的检查约束规定ID以已知子字符串开头,例如“EMP”或“CUST”。

但这些只是技巧而且几乎没有关系。理想情况下,人们会修改数据模型。希望这会有所帮助。