Sql server MSSQL约束可能导致循环或多个级联路径
我有这样一个场景:Sql server MSSQL约束可能导致循环或多个级联路径,sql-server,Sql Server,我有这样一个场景: 用户可以拥有多个帐户User也有比特币地址(他自己输入),它们是“取款地址”。每个账户也可能有多个比特币地址(即“存款地址”) 所有地址都在一个表中,唯一的区别是存款/取款仅由表BitcoinAddresses中的Type列指定 我想创建一个场景,删除用户将导致删除他拥有的所有提款比特币地址,同时删除他拥有的所有帐户。但是删除帐户会导致比特币地址引用设置为NULL 我试过这样的方法: CREATE TABLE [dbo].[Users] ( [Id]
用户
可以拥有多个帐户
User
也有比特币地址(他自己输入),它们是“取款地址”。每个账户
也可能有多个比特币地址(即“存款地址”)
所有地址都在一个表中,唯一的区别是存款/取款仅由表BitcoinAddresses
中的Type
列指定
我想创建一个场景,删除用户
将导致删除他拥有的所有提款比特币地址
,同时删除他拥有的所有帐户
。但是删除帐户
会导致比特币地址
引用设置为NULL
我试过这样的方法:
CREATE TABLE [dbo].[Users] (
[Id] NVARCHAR (128) NOT NULL,
[UserName] NVARCHAR (64) NULL,
CONSTRAINT [PK_dbo.Users] PRIMARY KEY CLUSTERED ([Id] ASC),
);
CREATE TABLE [dbo].[Accounts] (
[Id] BIGINT IDENTITY (1, 1) NOT NULL,
[UserId] NVARCHAR (128) NOT NULL,
[Number] BIGINT NOT NULL,
CONSTRAINT [PK_dbo.Accounts] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_dbo.Accounts.Users_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[Users] ([Id]) ON DELETE CASCADE
);
CREATE TABLE [dbo].[BitcoinAddresses] (
[BitcoinAddressId] INT IDENTITY (1, 1) NOT NULL,
[Address] NVARCHAR (MAX) NOT NULL,
[AccountId] BIGINT NULL,
[UserId] NVARCHAR (128) NULL,
[Type] NVARCHAR (MAX) NULL,
CONSTRAINT [PK_dbo.BitcoinAddresses] PRIMARY KEY CLUSTERED ([BitcoinAddressId] ASC),
CONSTRAINT [FK_dbo.BitcoinAddresses_dbo.Accounts_AccountId] FOREIGN KEY ([AccountId]) REFERENCES [dbo].[Accounts] ([Id]) ON DELETE SET NULL,
CONSTRAINT [FK_dbo.BitcoinAddresses_dbo.Users_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[Users] ([Id]) ON DELETE CASCADE
);
此解决方案会导致错误:
Introducing FOREIGN KEY constraint 'FK_dbo.BitcoinAddresses_dbo.Users_UserId' on table 'BitcoinAddresses' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
但很明显,我认为这种方法没有任何周期。你能解释一下为什么会发生这种行为吗?我怎样才能解决它?我想指出的是,我不想将Wihtdrawal和Deposit地址拆分为两个不同的表(因为这对于这个场景来说是一个正确的解决方案,但我想知道为什么我不能创建这样的引用)
这是我的把戏:如果你删除一个用户,他的帐户将被删除,他的
比特币地址将被删除。但是当他的帐户
被删除时,该帐户的比特币地址
也将更新为NULL
。这对于SQL Server来说太复杂了。它需要级联链简单、整洁,而不是分支和/或聚合。如果用户删除会导致删除比特币并将其帐户设置为NULL
,SQL Server如何知道您想要哪个?您是对的,但即使我将其设置为在每个引用上级联删除,也会给我相同的错误。是的,原因相同。两条级联路径会合。这是根本原因。SQL没有被编程为深入思考汇聚级联是否会导致问题。如果它看到潜在的收敛,则会引发一个错误。@TabAlleman请编辑您的naswer,从“SQL”到“SQL Server”。有一些othr SQL产品(如Postgres)可以很好地处理多个级联路径。SQL Server架构师选择禁止这样做(出于一些很好的原因,这里没有争论)。感谢编辑@ypercube。不幸的是,现在对我之前的评论进行同样的编辑已经太晚了。你的设计还有一个问题。比特币地址
中的一行可以引用具有不同用户ID的用户
和帐户
。这是故意的吗?如果没有,您可以删除两个FK并仅使用一个,使用:外键(UserId,AccountId)引用[dbo].[Accounts](UserId,Id)
,您将能够解决这两个问题;)哦,您需要在账户
中添加一个唯一的
约束来定义上述FK。将表拆分为两个似乎是最好的解决方案。一个只需要一个FK到用户(不需要AccountID列),另一个只需要到帐户。没有多个级联路径和更少的可空列。感谢您的建议。我知道我可以将它分为两个表,尽管在我的例子中并不容易,因为整个场景都是由实体框架管理的。因此,该框架确保我没有在一个比特币地址上有不同的帐户
和用户
。但是谢谢你的注意,接得好!