我有一个名为OptDefID
的主键的数据表。当删除此表中的记录时,我需要删除Permissions
表中OptDefID
字段defID
中Permissions
的所有记录。对我来说棘手的部分是Permissions
表没有主键并且拥有许多不同类型的权限,并且具有permissiontype
字段。我需要删除OptDefID
和permissiontype
OptDef
的行。
因为我需要考虑权限类型,我不相信外键约束在这里是适当的(或者是吗?)。
我也考虑过创建一个触发器,但我不确定如何将OptDefID传递给触发器。
我可以通过应用程序本身来做到这一点,但我觉得这应该是一个数据库级别的解决方案。
什么是最好的解决方案?
答案 0 :(得分:0)
如果仅在有问题的记录引用OptDefId
表时填充Permissions
列,则外键应该是合适的。即你有另一列MemberId
,它可以是Members
表上的外键。
只有当你有一个列时 - 让我们称之为ObjectId
- 当type
列的内容发生变化时,它会带来其他含义,即你不能使用外键。
在这种情况下,触发器可能是最好的方法,正如您已经猜到的那样。我只知道Oracle PL / SQL中的触发器,它们作为表示旧状态和新状态的单独完整行传递。我想它在MS-SQL-Server中类似。
答案 1 :(得分:0)
除了使用SELECT
语句加入,您还可以加入DELETE
&中的多个表格。 UPDATE
语句也是如此。
根据我的理解问题,您应该可以使用Permissions
列&列加入OptDefID
表格。添加类似于此的WHERE
子句:
DELETE MyTable
...
WHERE [Permissions].permissiontype = 'OptDef'
此外,这些链接也可能是有意义的:
答案 2 :(得分:0)
假设我要从权限中删除,其中defID为20,权限类型为“OptDef”。权限中可能有另一行的defID为20,但权限类型为“Member”。不应删除该节目,因为它与会员有关,而非选择数据。
在字段中存储表名可以防止外键正常工作,如您所发现的那样。
我建议你修复root问题并分开这两个外键,这样每个外键都可以单独执行。例如:
CREATE TABLE Permissions (
...
OptDefId int,
MemberId int,
FOREIGN KEY (OptDefId) REFERENCES OptDef ON DELETE CASCADE,
FOREIGN KEY (MemberId) REFERENCES Members ON DELETE CASCADE,
CHECK (
(OptDefId IS NOT NULL AND MemberId IS NULL)
OR (OptDefId IS NULL AND MemberId IS NOT NULL)
)
)
CHECK确保只有一个FK非NULL,并且只强制执行非NULL FK。
或者,您可以避免更改当前设计并通过触发器强制执行此“特殊”FK,但在可能的情况下,声明性约束应优先于触发器 - 声明性约束往往会留下更少的错误空间并且更加“自我记录” ”