表中有几个FK中的一个与多个级联路径

时间:2014-08-12 17:41:41

标签: sql-server database-design foreign-keys cascade

考虑以下3个表:

create table FOO (
    foo_index Numeric(38, 0)
        primary key clustered
        constraint foo_foo_index_nn not null
        identity(1,1)
)

create table BAR (
    bar_index Numeric(38, 0)
        primary key clustered
        constraint bar_bar_index_nn not null
        identity(1,1),
    foo_index Numeric(38, 0)
        constraint bar_foo_index_nn not null
        constraint bar_foo_index_fk references FOO(foo_index)
        on delete cascade
)

create table BAZ (
    baz_index Numeric(38, 0)
        primary key clustered
        constraint baz_baz_index_nn not null
        identity(1,1),
    foo_index Numeric(38, 0)
        constraint baz_foo_index_fk references FOO(foo_index)
        on delete cascade,
    bar_index Numeric(38, 0)
        constraint baz_bar_index_fk references BAR(bar_index)
        on delete cascade
)

每个bar都需要引用foo。虽然从表格创建中看不出来,但每个baz的目的是引用foo a bar,但不是两者都有。

如果您尝试创建上述架构,则会收到此错误:
Introducing FOREIGN KEY constraint 'baz_bar_index_fk' on table 'BAZ' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

一旦SQL Server检测到多个级联路径(在这种情况下,baz可能引用barfoo bar个引用,并且&# 39; foo`被删除)而不是试图检测级联循环,它只是不安全。

但是,在实际使用中不会发生这种情况,因为计划只允许2个外键中的一个非空。有没有什么方法可以指示SQL Server的使用限制,以便它允许两个FK在级联上删除?

1 个答案:

答案 0 :(得分:0)

我认为您的设计存在错误,因为它不是典型的外键约束A Column Referencing a A TABLE。你不能在这里有一个外键约束,这是一个更复杂的业务需求和一个简单的约束,如外键约束不足以满足这个要求......

我的建议

1)将NUMERIC(38,0)更改为INT,这些都是标识列,每次都会增加1,我没有看到将此列作为NUMERIC 38的点,这将是一个17字节的数据类型。 INT将在此表中为您提供超过20亿行,bigint将为您提供2 ^ 63行,更不用说bigint限制如果您的表有任何接近20亿行,您应该考虑分区它不添加更大的数据类型以添加​​更多行,如此巨大的表,你的表现将达到最低点。

2)正如你在表BAZ中提到的那样,一行只会引用回BAR或FOO我看不到有两列的点,Add One列引用回到任一表并添加另一列最小数据type(一个好的候选位数据类型)来标识引用的表。

我会创建这样的BAZ表格.....

create table BAZ 
(
    baz_index INT primary key clustered
              constraint baz_baz_index_nn not null identity(1,1),
    bar_Fo_index INT,
    Is_Bar       BIT     --<--  1 is bar 0 is foo      
) 

级联操作

对于级联更新,删除或插入使用存储过程。