具有条件外键的数据库模型
Database model with condition foreign key
我需要根据这些条件对数据库建模:
- 一个 table 代表
Projects
- 另一个 table
Programmers
- 程序员可以是
Senior
或Junior
- 每个项目可能有几个程序员,但至少必须有一个高级。
我想定义某种条件外键,以确保在项目中包含的所有程序员中至少有一个是资深的。也没有高级程序员可以降级为初级程序员,尽管可能会发生相反的情况。
我不知道如何在不借助某些业务逻辑的情况下创建这种约束。
不幸的是,您必须依赖一些业务逻辑来实现您想要的。
您可以将 Senior 和 Junior 的属性限制为这两个值,但您无法在 table 级别显示升级功能。
你想要的基本上是一个检查某些约束的触发器,但 Access 不支持数据库触发器。一种解决方法是使 senior-junior-attribute 只能以一种形式进行更改。在这种形式中,您将 AfterUpdate-event 或 BeforeUpdate-event 连接到绑定到属性的文本框,并通过 VBA-code 检查业务逻辑。
你的至少一个高级约束也是如此。
一些代码是否可以提供更多帮助?
有时考虑有两种不同的约束而不是一种具有特殊条件的约束会奏效。
例如条件一:每个项目必须有高级程序员负责;条件 2:每个项目可以分配任意数量的高级或初级程序员。
create table Programmers(
ID counter constraint PK_Programmers primary key,
Name text,
Seniority char( 1 ) check( Seniority in( 'S', 'J' ),
...,
constraint UQ_Programmer_seniority unique( ID, Seniority ),
constraint CK_Programmer_Seniority check( Seniority in( 'S', 'J' ))
);
create table Project(
ID counter constraint PK_Projects primary key,
Name text,
SrProg int,
SrFlag char( 1 ) default 'S',
...,
constraint SK_Project_SrFlag check( SrFlag = 'S' ),
constraint FK_Project_SrProgrammer foreign key( SrProg, SrFlag )
references Programmers( ID, Seniority )
);
所以高级程序员是一个 1-1 FK 定义为项目元组的一部分。除非程序员被定义为 'S'(高级),否则不能引用,并且一旦引用,该程序员的 'S' 不能更改为 'J'。
至于其他程序员,使用标准交集table。由于这些程序员的资历并不重要,参考中的PK就可以了。
create table Project_Programmers(
ProjID int not null,
ProgID int not null,
constraint PK_Project_Programmers primary key( ProjID, ProgID ),
constraint FK_Project_Programmers_Project foreign key( ProjID )
references Projects( ID ),
constraint FK_Project_Programmers_Programmer foreign key( ProgID )
references Programmers( ID )
);
因为资历指标不是这些 FK 的一部分,资历指标 'J' 可以毫无问题地更改为 'S' 或从 'S' 更改为 'J'如果该程序员未被定义为项目的强制高级程序员。面对现实吧,有时不得不降职。这为您提供了额外的保护,可以将降级的程序员指定为任何项目的 高级程序员。在将他们从所有此类职位中删除之前,无法进行降级。
我需要根据这些条件对数据库建模:
- 一个 table 代表
Projects
- 另一个 table
Programmers
- 程序员可以是
Senior
或Junior
- 每个项目可能有几个程序员,但至少必须有一个高级。
我想定义某种条件外键,以确保在项目中包含的所有程序员中至少有一个是资深的。也没有高级程序员可以降级为初级程序员,尽管可能会发生相反的情况。
我不知道如何在不借助某些业务逻辑的情况下创建这种约束。
不幸的是,您必须依赖一些业务逻辑来实现您想要的。
您可以将 Senior 和 Junior 的属性限制为这两个值,但您无法在 table 级别显示升级功能。
你想要的基本上是一个检查某些约束的触发器,但 Access 不支持数据库触发器。一种解决方法是使 senior-junior-attribute 只能以一种形式进行更改。在这种形式中,您将 AfterUpdate-event 或 BeforeUpdate-event 连接到绑定到属性的文本框,并通过 VBA-code 检查业务逻辑。
你的至少一个高级约束也是如此。
一些代码是否可以提供更多帮助?
有时考虑有两种不同的约束而不是一种具有特殊条件的约束会奏效。
例如条件一:每个项目必须有高级程序员负责;条件 2:每个项目可以分配任意数量的高级或初级程序员。
create table Programmers(
ID counter constraint PK_Programmers primary key,
Name text,
Seniority char( 1 ) check( Seniority in( 'S', 'J' ),
...,
constraint UQ_Programmer_seniority unique( ID, Seniority ),
constraint CK_Programmer_Seniority check( Seniority in( 'S', 'J' ))
);
create table Project(
ID counter constraint PK_Projects primary key,
Name text,
SrProg int,
SrFlag char( 1 ) default 'S',
...,
constraint SK_Project_SrFlag check( SrFlag = 'S' ),
constraint FK_Project_SrProgrammer foreign key( SrProg, SrFlag )
references Programmers( ID, Seniority )
);
所以高级程序员是一个 1-1 FK 定义为项目元组的一部分。除非程序员被定义为 'S'(高级),否则不能引用,并且一旦引用,该程序员的 'S' 不能更改为 'J'。
至于其他程序员,使用标准交集table。由于这些程序员的资历并不重要,参考中的PK就可以了。
create table Project_Programmers(
ProjID int not null,
ProgID int not null,
constraint PK_Project_Programmers primary key( ProjID, ProgID ),
constraint FK_Project_Programmers_Project foreign key( ProjID )
references Projects( ID ),
constraint FK_Project_Programmers_Programmer foreign key( ProgID )
references Programmers( ID )
);
因为资历指标不是这些 FK 的一部分,资历指标 'J' 可以毫无问题地更改为 'S' 或从 'S' 更改为 'J'如果该程序员未被定义为项目的强制高级程序员。面对现实吧,有时不得不降职。这为您提供了额外的保护,可以将降级的程序员指定为任何项目的 高级程序员。在将他们从所有此类职位中删除之前,无法进行降级。