Sql server 当我在删除/更新级联时不使用引用完整性时,外键有意义吗 我不希望在删除客户时删除订单。(关于删除级联) 我使用标识列,因此不需要更新级联 虽然存在指向/引用客户的订单,但应该可以删除客户表。我不在乎客户何时离开,因为我仍然需要其他表的订单表
当我在删除/更新级联时不使用引用完整性时,外键在这种情况下有意义吗?是。外键的存在不仅是为了在您自己之后进行清理,而且主要是为了首先确保数据是正确的(在某些情况下,它还可以帮助优化器)。我到处使用外键,但我还没有发现需要实现级联操作。我确实理解级联的目的,但我总是发现自己控制这些过程更好 编辑尽管我已经试图解释您可以解决级联问题(因此仍然满足您的第三个条件),但我还是想添加一个说明: 当然,在删除客户后,您仍然可以保留订单。关键是使Sql server 当我在删除/更新级联时不使用引用完整性时,外键有意义吗 我不希望在删除客户时删除订单。(关于删除级联) 我使用标识列,因此不需要更新级联 虽然存在指向/引用客户的订单,但应该可以删除客户表。我不在乎客户何时离开,因为我仍然需要其他表的订单表,sql-server,foreign-keys,referential-integrity,Sql Server,Foreign Keys,Referential Integrity,当我在删除/更新级联时不使用引用完整性时,外键在这种情况下有意义吗?是。外键的存在不仅是为了在您自己之后进行清理,而且主要是为了首先确保数据是正确的(在某些情况下,它还可以帮助优化器)。我到处使用外键,但我还没有发现需要实现级联操作。我确实理解级联的目的,但我总是发现自己控制这些过程更好 编辑尽管我已经试图解释您可以解决级联问题(因此仍然满足您的第三个条件),但我还是想添加一个说明: 当然,在删除客户后,您仍然可以保留订单。关键是使Orders.CustomerID列可为空,例如 CREATE
Orders.CustomerID
列可为空,例如
CREATE TABLE dbo.Customers(CustomerID INT PRIMARY KEY);
CREATE TABLE dbo.Orders(OrderID INT PRIMARY KEY, CustomerID INT NULL
FOREIGN KEY REFERENCES dbo.Customers(CustomerID));
现在,当您想删除客户时,假设您通过存储过程控制这些操作,您可以这样做,首先将他们的订单设置为NULL
CREATE PROCEDURE dbo.Customer_Delete
@CustomerID INT
AS
BEGIN
SET NOCOUNT ON;
UPDATE dbo.Orders SET CustomerID = NULL
WHERE CustomerID = @CustomerID;
DELETE dbo.Customers
WHERE CustomerID = @CustomerID;
END
GO
如果无法控制客户表中的即席删除,则仍然可以使用instead of触发器实现这一点:
CREATE TRIGGER dbo.Cascade_CustomerDelete
ON dbo.Customers
INSTEAD OF DELETE
AS
BEGIN
SET NOCOUNT ON;
UPDATE o SET CustomerID = NULL
FROM dbo.Orders AS o
INNER JOIN deleted AS d
ON o.CustomerID = d.CustomerID;
DELETE c
FROM dbo.Customers AS c
INNER JOIN deleted AS d
ON c.CustomerID = d.CustomerID;
END
GO
总而言之,我不确定我是否理解删除客户并保留其订单(或任何关于谁下订单的指示)的目的。是的。外键的存在不仅是为了在您自己之后进行清理,而且主要是为了首先确保数据是正确的(在某些情况下,它还可以帮助优化器)。我到处使用外键,但我还没有发现需要实现级联操作。我确实理解级联的目的,但我总是发现自己控制这些过程更好
编辑尽管我已经试图解释您可以解决级联问题(因此仍然满足您的第三个条件),但我还是想添加一个说明:
当然,在删除客户后,您仍然可以保留订单。关键是使Orders.CustomerID
列可为空,例如
CREATE TABLE dbo.Customers(CustomerID INT PRIMARY KEY);
CREATE TABLE dbo.Orders(OrderID INT PRIMARY KEY, CustomerID INT NULL
FOREIGN KEY REFERENCES dbo.Customers(CustomerID));
现在,当您想删除客户时,假设您通过存储过程控制这些操作,您可以这样做,首先将他们的订单设置为NULL
CREATE PROCEDURE dbo.Customer_Delete
@CustomerID INT
AS
BEGIN
SET NOCOUNT ON;
UPDATE dbo.Orders SET CustomerID = NULL
WHERE CustomerID = @CustomerID;
DELETE dbo.Customers
WHERE CustomerID = @CustomerID;
END
GO
如果无法控制客户表中的即席删除,则仍然可以使用instead of触发器实现这一点:
CREATE TRIGGER dbo.Cascade_CustomerDelete
ON dbo.Customers
INSTEAD OF DELETE
AS
BEGIN
SET NOCOUNT ON;
UPDATE o SET CustomerID = NULL
FROM dbo.Orders AS o
INNER JOIN deleted AS d
ON o.CustomerID = d.CustomerID;
DELETE c
FROM dbo.Customers AS c
INNER JOIN deleted AS d
ON c.CustomerID = d.CustomerID;
END
GO
总而言之,我不确定我是否理解删除客户并保留其订单(或任何关于下订单人的指示)的目的。因此,要明确的是,目前客户与订单之间存在FK。此关系上未启用级联更新/删除。您的计划是删除客户,但允许保留订单
这将违反外键约束;并防止发生删除。
如果禁用约束,执行删除,然后重新启用,则可以使其工作
但是,这将在系统中留下孤立的订单记录;从长远来看,这可能会使支持变得更加困难。下一个支持这一点的人会怎么想
保留记录并添加活动/非活动或创建和非活动日期的状态不是更好吗
我正在努力破坏数据库的完整性以减少空间。。。?或者,删除的主要原因是什么
如果您不想总是筛选出不再活动的记录,请使用创建活动客户集合的视图或包。删除一些但不是所有的数据对我来说似乎是错误的。所以要明确的是,目前客户和订单之间存在FK。此关系上未启用级联更新/删除。您的计划是删除客户,但允许保留订单
这将违反外键约束;并防止发生删除。
如果禁用约束,执行删除,然后重新启用,则可以使其工作
但是,这将在系统中留下孤立的订单记录;从长远来看,这可能会使支持变得更加困难。下一个支持这一点的人会怎么想
保留记录并添加活动/非活动或创建和非活动日期的状态不是更好吗
我正在努力破坏数据库的完整性以减少空间。。。?或者,删除的主要原因是什么
如果您不想总是筛选出不再活动的记录,请使用创建活动客户集合的视图或包。删除一些但不是所有的数据对我来说似乎是错误的。我完全不理解你的答案,因为如果你说是,我应该在我的场景中使用它们,但这个答案打破了条件“3”:我想删除一个客户,尽管有些订单引用了该客户。请更正您的解决方案。@您的问题是“在这种情况下,当我不使用删除/更新级联上的引用完整性时,外键有意义吗?”如果这不是您希望人们回答的问题,请更正您的问题。也许我的示例客户的订单很愚蠢。这只是一个例子来说明一个问题。我只想允许用户从父表中删除数据,但子表数据应该仍然能够读取。使用on delete cascade或外键。我不能这样做。exoption是从1个客户到*.N订单的可空/可选关系。这个解决方案只是预先准备好的