0

我有一个带有主键的数据表,名为OptDefID. 当此表中的记录被删除时,我需要从Permissions表中删除字段中包含OptDefID该记录的所有记录defID(in Permissions)。对我来说棘手的部分是该Permissions表没有主键并且拥有许多不同类型的权限,并且有一个permissiontype字段。我需要删除具有OptDefIDAND 的permissiontypeOptDef

因为我需要考虑权限类型,所以我认为外键约束在这里不合适(或者是吗?)。

我也考虑过创建触发器,但不确定如何将 OptDefID 传递到触发器中。

我可以通过应用程序本身来做到这一点,但我觉得这应该是一个数据库级的解决方案。

最好的解决方案是什么?

4

3 回答 3

0

如果OptDefId仅在相关记录引用Permissions表时填充该列,则外键应该是合适的。即你有另一列MemberId,这又可能是Members表上的外键。

只有当您有一个列 - 我们称之为它ObjectId- 随着type列内容的变化而具有其他含义时,您才能使用外键。在这种情况下,触发器可能是最好的方法,正如您已经猜到的那样。我只知道 Oracle PL/SQL 中的触发器,它们作为单独的完整行传入,代表新旧状态。我想这在 MS-SQL-Server 中会类似。

于 2012-11-12T14:44:50.553 回答
0

除了使用 join withSELECT语句外,您还可以在DELETE&UPDATE语句中连接多个表。

据我了解这个问题,您应该能够将Permissions表连接到具有OptDefID列的表并添加WHERE类似于以下内容的子句:

DELETE MyTable
...
WHERE [Permissions].permissiontype = 'OptDef'

此外,这些链接也可能很有趣:

于 2012-11-12T14:50:30.257 回答
0

假设我想从 defID 为 20 且权限类型为“OptDef”的权限中删除。Permissions 中可能还有另一行,其 defID 为 20,但权限类型为“Member”。不应删除该节目,因为它与会员有关,而不是 Opt 数据。

正如您所发现的,在字段中存储表名会阻止外键正常工作。

我建议您解决根本问题并将这两个外键分开,以便可以单独强制执行它们中的每一个。例如:

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,但在可能的情况下,应优先使用声明性约束而不是触发器 - 声明性约束往往留出更少的错误空间并且更加“自我记录”。

于 2012-11-12T16:19:58.177 回答