条件外键关系


14

我目前在两个实体之间有一个外键,我想使该关系以表之一的entityType为条件。这是表格的层次结构,这是通过FK从孩子到父母的折算完成的

                  Store
            /                \
  Employees                    \
                             TransactionalStores
                            /       |         \
                     Kiosks         |          BrickMortars
                                 Onlines

我目前有从员工到商店的FK关系

ALTER TABLE Employees ADD CONSTRAINT Employee_Store
            FOREIGN KEY (TransStoreId)
            REFERENCES TransactionalStores(StoreId)

我想添加条件:

WHERE TransactionalStores.storeType != 'ONLINE_TYPE'

这是否可能,或者我必须将TransactionalStores分为两个新的子类型(例如PhysicalStores和VirtualStores)


Answers:


18

外键可以设置为条件。您没有显示每个表的布局,因此这是显示您的关系的典型设计:

create table TransactionalStores(
    ID        int   not null auto_increment,
    StoreType char  not null,
    ..., -- other data
    constraint CK_TransStoreType check( StoreType in( 'B', 'K', 'O' )),
    constraint PK_TransactionalStores primary key( ID ),
    constraint UQ_TransStoreTypes unique( ID, StoreType ) -- for FK references
);
create table Kiosks(
    ID         int   not null,
    StoreType  char  not null,
    ..., -- other Kiosk data
    constraint CK_KioskStoreType check( StoreType = 'K' ), -- kiosks only
    constraint PK_Kiosks primary key( ID, StoreType ),
    constraint FK_Kiosks_TransStores foreign key( ID, StoreType )
        references TransactionalStores( ID, StoreType )
);

Onlines和BrickMorters具有相同的基本结构,但StoreType视情况限制为仅'O'或'B'。

现在,您希望从另一个表引用一个TransactionalStores(并通过它引用到各个store表),但仅限于Kiosks和BrickMorter。唯一的区别是约束:

create table Employees(
    ID         int       not null,
    StoreID    int,
    StoreType  char,
    ..., -- other Employee data
    constraint PK_Employees primary key( ID ),
    constraint CK_Employees_StoreType check( coalesce( StoreType, 'X' ) <> 'O' )), -- Online not allowed
    constraint FK_Employees_TransStores foreign key( StoreID, StoreType )
        references TransactionalStores( ID, StoreType )
);

在此表中,FK参考将StoreType强制为“ K”,“ O”或“ B”,但字段约束进一步将其限制为“ K”或“ B”。

为了说明起见,我使用了检查约束来限制TransactionStores表中的商店类型。在现实生活中,将StoreType用作该表的FK的StoreTypes查找表可能是更好的设计选择。


9

不能将外键设置为条件,因此这是不可能的。业务规则似乎是,员工只能在一个实体商店中工作。因此,您建议的超级商店类型有两个子类型: 实体在线。每个实体店都可以配备一个或多个员工,并且每个员工必须分配给一个实体店和一个实体店。然后,实体商店有两个子类型,Brick和MortarKiosk。具有三个直接子类型-KioskOnlineBrick and Mortar-隐藏每个商店拥有的财产-不论是否可以在实际位置找到。现在,该设计依靠人工来理解子类型名称中固有的语义,以了解在线商店没有员工。在声明的模式中这并不容易理解,必须以触发器的形式编写代码,以DBMS可以强制执行的方式表达这种理解。如《数据库专业人员的应用数学》一书中所示,开发,测试和维护不影响性能的触发器是要实施的难度更大的解决方案。

商店进行子类型化首先是针对其位置类型,然后对实体商店的结构进行子类型化,这是关于业务规则的更正确设计,并且无需编写代码来执行规则。一旦将属性明确地包含为可以用作子类型的区分符的商店位置类型,就可以直接在员工和实体商店之间建立关系,从而仅使用外键约束就可以完全实施该规则。ere是使用Oracle SQL Developer数据建模器创建的数据模型,该模型显示了使用Barker-Ellis的超级和子类型超级和子类型的Box in box表示法,我更喜欢它的优雅表现。该图现在也可以清楚地显示规则。

在此处输入图片说明

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.