我有一个关于对我的表强制执行约束的问题。我有一张名为 workson 的桌子和一张名为 staff 的桌子,每个员工都有特定的头衔(主管、授权人、经理……)。我需要确保主管和授权人不能是工作表上的同一员工。他们之间的基数是多对多的。我不知道该怎么做。你能建议我解决这个问题吗?
谢谢
我有一个关于对我的表强制执行约束的问题。我有一张名为 workson 的桌子和一张名为 staff 的桌子,每个员工都有特定的头衔(主管、授权人、经理……)。我需要确保主管和授权人不能是工作表上的同一员工。他们之间的基数是多对多的。我不知道该怎么做。你能建议我解决这个问题吗?
谢谢
一些数据库支持检查约束:
CREATE TABLE workson
(
rowId int NOT NULL,
supervisorId int NOT NULL,
authorizerId int NOT NULL,
-- ...
CONSTRAINT chk_Uniqueness CHECK (supervisorId != authorizerId)
)
考虑以下查询
SELECT AssignmentNo, StaffNo
FROM worksOnStaff
WHERE StaffType = 'supervisor'
INTERSECT
SELECT AssignmentNo, StaffNo
FROM worksOnStaff
WHERE StaffType = 'authorizer'
当表中的数据满足您的约束时,上述查询将是空集,即
CHECK ( NOT EXISTS ( SELECT AssignmentNo, StaffNo
FROM worksOnStaff
WHERE StaffType = 'supervisor'
INTERSECT
SELECT AssignmentNo, StaffNo
FROM worksOnStaff
WHERE StaffType = 'authorizer' ) );
问题是,很少有 SQL 产品允许在CHECK
约束中使用子查询。
通常的解决方法是在过程代码中实现相同的逻辑,例如使用触发器或强制用户通过存储过程更新数据(通过删除基表上的更新权限),以确保永远不会违反约束。您必须注意正确地序列化更新,而不会使整个事情像胶水一样运行。
令人高兴的是,有一本关于这个主题的优秀书籍:
Lex de Haan、Toon Koppelaars 为数据库专业人员提供应用数学
对于无法向 DBMS 声明的约束的实现,我们更倾向于遵循触发程序策略……和声明的约束一样,触发程序策略不能被颠覆;...可能会创建一个更易于管理的代码架构 ...[然而]通过触发器为这些约束实现有效的数据完整性代码绝非易事...但是,您将通过定期实现表约束来体验这一点并且精通这样做,在程序上实现表约束通常是非常可行的......
执行模型 EM6:On-Transition-Effect-Property Plus Optimized-Query
- 将正式规范转换为约束验证查询。
- 开发代码来维护过渡效果。
- 设计转换效果 (TE) 查询,确保仅在必要时运行约束验证查询。
- 通过让 TE 查询提供可在验证查询中使用的值,发现一种优化约束验证查询的方法。
- 设计并向数据完整性 (DI) 代码添加序列化策略。
他们详细介绍了如何在 Oracle 中实施这种可以移植到其他 SQL 产品的策略。