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订单的可空/可选关系。这个解决方案只是预先准备好的