考虑以下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
可能引用bar
和foo
bar
个引用,并且&# 39; foo`被删除)而不是试图检测级联循环,它只是不安全。
答案 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
)
对于级联更新,删除或插入使用存储过程。