【发布时间】:2015-05-22 12:43:24
【问题描述】:
我有这样一个场景:
User 可以拥有多个Accounts。 User 也有比特币地址(他自己输入的),它们是“提现地址”。每个Account 也可能有多个比特币地址(即“存款地址”)。
所有地址都在一个表中,唯一的区别是存款/取款仅由表BitcoinAddresses中的列Type指定。
我想创建一个场景,删除User会导致他拥有的所有提款BitcoinAddresses被删除,同时他拥有的所有Accounts也被删除。但是删除Account 应该会导致BitcoinAddresses 引用设置为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.
但显然我在这种方法中看不到任何循环。你能向我解释为什么会发生这种行为吗?我该如何解决?我想指出,我不想将提款和存款地址拆分为两个不同的表(因为这将是这种情况下的正确解决方案,但我想知道为什么我不能创建此类引用)
这是我的小提琴:http://sqlfiddle.com/#!6/5d9cd
【问题讨论】:
-
您的设计还有一个问题。
BitcoinAddresses中的一行可以引用User和具有不同UserIds 的Account。这是故意的吗?如果没有,您可以删除 2 个 FK 并仅使用一个,使用:FOREIGN KEY (UserId, AccountId) REFERENCES [dbo].[Accounts] (UserId, Id),您将能够解决您的两个问题 ;) 哦,您需要在Accounts中添加一个UNIQUE约束上面要定义的FK。 -
将表格一分为二似乎是最好的解决方案。一个只需要用户的 FK(并且没有 AccountID 列),另一个只需要 Accounts。没有多个级联路径和较少可为空的列。
-
感谢您的建议。我知道我可以将它分成两个表,尽管在我的情况下这并不容易,因为整个场景都是由实体框架管理的。因此,该框架确保我没有遇到在一个
BitcoinAddress上有不同的Account和User的情况。但是感谢您的关注,好消息!
标签: sql-server