删除父项时删除子行的最简单方法是什么,而不知道其父项是什么?

时间:2015-06-24 14:07:15

标签: sql sql-server database tsql database-design

给定多种实体类型:

  1. Cluster
  2. Hypervisor
  3. VirtualMachine
  4. 并且给定可能属于其中任何一个的属性(但每行不超过一个):

    • CpuInfo
      • CpuSpeed
      • CpuTotal
      • ...
    • DataStore
    • ...

    使用父级删除属性的最简单方法是什么?

    尝试解决方案

    ON DELETE CASCADE

    ON DELETE CASCADE似乎需要为每个可能的父母提供一个可以为空的外键,这让我感到很糟糕:

    CREATE TABLE CpuInfo
    (
        -- Properties
        Id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
        CpuSpeed INT,
        AllocatedTotal INT,
        CpuTotal INT,
        AvailableTotal INT,
    
        -- Foreign keys for all possible parents
        ClusterId INT,
        HypervisorId INT,
        VirtualMachineId INT,
    
        FOREIGN KEY (ClusterId) REFERENCES Cluster(Id) ON DELETE CASCADE,
        FOREIGN KEY (HypervisorId) REFERENCES Hypervisor(Id) ON DELETE CASCADE,
        FOREIGN KEY (VirtualMachineId) REFERENCES VirtualMachine(Id) ON DELETE CASCADE
    );
    

    带触发器的结点表

    父母通过联结表与财产相关。例如:

    CREATE TABLE HypervisorCpuInfo
    (
        HypervisorId INT NOT NULL,
        CpuInfoId INT NOT NULL,
    
        FOREIGN KEY (HypervisorId) REFERENCES Hypervisor(Id),
        FOREIGN KEY (CpuInfoId) REFERENCES CpuInfo(Id) ON DELETE CASCADE
    );
    

    每种实体类型都有一个DELETE触发器。触发器选择实体属性的ID并删除它们。删除属性后,也会通过ON CASCADE DELETE删除子连接行。

    但是,这并不能很好地为业务规则建模,因为它允许相同的CpuInfo属于多个实体。它还为设计添加了许多表格。

    是否有更简单的解决方案?

1 个答案:

答案 0 :(得分:2)

我认为"联合表"可能适合DRYness(由于1:n的关系,它不是一个真正的交汇点)

你可以打电话给你的联盟表" a"超级表" (类似于"机器" [抱歉我不是本地人]):

在此表中,您将所有键都放在属性中(使每个外键列唯一,以确保1:1 *)。您机器的类型" (ClusterHypervisorVirtualMachine)位于"三键&#​​34;你已经尝试过 - 也在超级表中。 确保"机器"只有一个实体添加约束:

ALTER TABLE CpuInfo WITH CHECK ADD CONSTRAINT [CK_keyIDs] CHECK (
(ClusterId IS NULL AND HypervisorId IS NULL AND VirtualMachineId IS NOT NULL)
OR (ClusterId IS NULL AND HypervisorId IS NOT NULL AND VirtualMachineId IS NULL)
OR (ClusterId IS NOT NULL AND HypervisorId IS NULL AND VirtualMachineId IS NULL)) GO

好消息是你对自己的实体免费,你可以允许PC同时成为Cluster

*关键栏目! ID必须是唯一的