SQL Server - 使用递归外键进行级联 DELETE

2024-02-12

我花了很多时间试图找出如何实现删除时级联SQL Server 上的递归主键已经有一段时间了。我已经阅读了有关触发器、创建临时表等的内容,但尚未找到适合我的数据库设计的答案。

这是一个用于演示目的的老板/员工数据库示例:

TABLE employee
id|name     |boss_id
--|---------|-------
1 |John     |1
2 |Hillary  |1
3 |Hamilton |1
4 |Scott    |2
5 |Susan    |2
6 |Seth     |2
7 |Rick     |5
8 |Rachael  |5

正如您所看到的,每个员工都有一个老板,同时也是一名员工。所以,id/boss_id上存在PK/FK关系。

这是包含其信息的(缩写)表:

TABLE information
emp_id|street     |phone
------|-----------|-----
2     |blah blah  |blah
6     |blah blah  |blah
7     |blah blah  |blah

在employee.id/information.emp_id 上有一个带有级联删除的PK/FK。

例如,如果 Rick 被解雇,我们会这样做:

DELETE FROM employee WHERE id=7

这应该从员工和信息中删除 Rick 的行。耶级联!

现在,假设我们已经度过了困难时期,我们需要放弃汉密尔顿和他的entire部门。这意味着我们需要删除

  • Hamilton
  • Scott
  • Susan
  • Seth
  • Rick
  • Rachael

当我们运行时,从员工和信息表中:

DELETE FROM employee WHERE id=3

我为 id/emp_id 尝试了一个简单的 CASCADE ON DELETE,但 SQL Server 没有:

Introducing FOREIGN KEY constraint 'fk_boss_employee' on table 'employee' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

我能够在 Access 中的测试数据库上使用 CASCADE ON DELETE,并且它的行为完全符合我的预期。再说一遍,我want如果删除了父母、祖父母、曾祖父母等,则将删除父母的每个可能的孩子、孙子女、曾孙子女等。

当我尝试使用触发器时,我似乎无法让它自行触发(例如,当您尝试删除 Hamilton 的员工 Susan 时,首先查看 Susan 是否有任何员工等),更不用说删除 N 个员工了。

所以!我想我已经提供了我能想到的所有细节。如果还有不清楚的地方,我会尽力改进这个描述。


死灵术。
有两个简单的解决方案。

  • You can either read Microsoft's sorry-excuse(s) of why they didn't implement this (because it is difficult and time-consuming - and time is money), and explanation of why you don't/shouldn't need it (although you do), and implement the delete-function with a cursor in a stored procedure
    • 因为你并不真正需要删除级联,因为你总是有时间随时随地更改你和所有其他人的所有代码(例如与其他系统的接口),从而删除一个员工(或多个员工,注意:复数)(包括此数据库中的所有上级和从属对象[包括添加一个或多个新对象](以及其他客户的此数据库的任何其他副本,特别是在生产中,当您无权访问数据库时[哦,并且关于测试系统、集成系统以及生产、测试​​和集成的本地副本]

or

  • 您可以使用实际上支持递归级联删除的适当 DBMS,例如 PostGreSQL(只要图是有向的,并且是非循环的;否则删除时会出现错误)。

PS:
那是讽刺。



Note:

只要您的删除不是源于级联,并且您只想在自引用表上执行删除,您就可以删除任何条目,只要您在子句中也删除所有从属对象即可。

因此,要删除此类对象,请执行以下操作:

;WITH CTE AS 
(
    SELECT id, boss_id, [name] FROM employee
    -- WHERE boss_id IS NULL 
    WHERE id = 2 -- <== this here is the id you want to delete !

    UNION ALL

    SELECT employee.id, employee.boss_id, employee.[name] FROM employee
    INNER JOIN CTE ON CTE.id = employee.boss_id 
)
DELETE FROM employee 
WHERE employee.id IN (SELECT id FROM CTE)

假设您有以下表结构:

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'dbo.employee') AND type in (N'U'))
BEGIN
CREATE TABLE dbo.employee
(
    id int NOT NULL,
    boss_id int NULL,
    [name] varchar(50) NULL,
    CONSTRAINT PK_employee PRIMARY KEY ( id )
); 
END
GO

IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'dbo.FK_employee_employee') AND boss_id_object_id = OBJECT_ID(N'dbo.employee'))
ALTER TABLE dbo.employee  WITH CHECK ADD  CONSTRAINT FK_employee_employee FOREIGN KEY(boss_id)
REFERENCES dbo.employee (id)
GO

IF  EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'dbo.FK_employee_employee') AND boss_id_object_id = OBJECT_ID(N'dbo.employee'))
ALTER TABLE dbo.employee CHECK CONSTRAINT FK_employee_employee
GO
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SQL Server - 使用递归外键进行级联 DELETE 的相关文章

  • 从 Excel 将参数传递到 SQL Server 上的 MS Query 中的临时变量

    我已经使用 Microsoft 查询创建了参数查询 如上所述here https superuser com questions 197453 run an sql query with a parameter from excel 200
  • 从一条记录中获取多条记录

    我有一个包含 2 列的表 名称为字符串 数量为整数 例如我需要每条记录的数量 X 数量字段 Name Qty Dave 25 Nathan 10 Chaim 8 我需要 Dave 提供的来自 nathan 10 和 chaim 8 的 25
  • Linq 查询可以从 Sql 数据库检索 BLOB 吗?

    Linq 查询可以从 Sql 数据库检索 BLOB 吗 他们是怎么出来的 LINQ To SQL 类为 SQL Server 中的所有二进制和 varbinary 字段创建 System Data Linq Binary 类型的属性 Bin
  • 使用 impala 按范围连接表的有效方法

    我第一个有下表 Range 包括值范围和附加列 row From To Country 1 1200 1500 2 2200 2700 3 1700 1900 4 2100 2150 The From and Toare bigint并且是
  • T-SQL参数嗅探重新编译计划

    我有 SQL 命令 exec sp executesql N SELECT TOP 10 FROM mytableView WHERE Name LIKE Value0 ORDER BY Id DESC N Value0 varchar 5
  • 我可以将 UseCSharpNullComparisonBehavior 用于单个查询吗?

    我有一个查询 该查询曾经是存储过程 现已转换为 EF 查询 现在已经超时了 使用 SQL Profiler 我可以看到生成的 SQL 的唯一区别是 EF 转变的新行为entity Property value into entity Pro
  • SQL Union All 查询中的排序规则冲突

    有一个 Union All 查询 如下所示 当在 SQL Server 中触发时 出现错误 无法解决 SELECT 语句中第 1 列的排序规则冲突 请问 在哪里添加带有此 Union All 查询的 Collat e database de
  • 删除 SQL 中重复的字段条目

    无论如何 我可以删除某个表中的所有重复条目 users 这是我拥有的条目类型的示例 我必须说一下桌子users由3个字段组成 ID user and pass mysql query DELETE FROM users WHERE or d
  • 如何检查 SQL Server 数据库的 Azure 定价层更改历史记录?

    两个月前 我创建了一个具有 S0 定价层的 AZURE SQL 数据库 但不知何故 同一数据库的定价等级突然升级到 P15 持续 10 天 然后再次降级到 S0 我想查一下这是何时以及如何发生的 有什么方法可以从 Azure 门户或使用任何
  • DB2 vs PostgreSQL vs SQL Server [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 有人用过这三个数据库吗 你和他们有什么经历 PostgreSQL 对于一个项目来说看起来相当诱人 但我很想了解更多关于它的信息 我们是一家 NE
  • 更新或插入 SQL Server 时忽略错误行

    我的项目必须处理巨大的数据库 在最坏的情况下 它可能是超过8000万行 现在 我有 2 张桌子T1 and T2 我必须从表中复制数据T1到餐桌T2 如果表中的一行T1表中已存在T2 相同主键 然后更新该行其他列的数据T1 to T2 否则
  • 为什么没有主键的表是一个坏主意?

    我对数据建模非常陌生 根据微软的实体框架 不允许使用没有主键的表 这显然是一个坏主意 我试图找出为什么这是一个坏主意 以及如何修复我的模型 这样我就不会出现这个漏洞 我当前的模型中有 4 个表 User City HelloCity 和 R
  • 从数据库中删除样式 (SQL Server)

    我正在处理旧的数据库表 其中有附加了 CSS 的值 例如 font size 4 Select your gender font font size 4 Select your country font 除了一次删除一个样式之外 还有什么方
  • CHAR(64) 或 BINARY(32) 在 SQL SERVER 中存储 SHA256 哈希

    我正在讨论在 SQL Server 中存储 SHA256 哈希时使用哪种数据类型 应该是 CHAR 64 还是 BINARY 32 该列将成为唯一聚集索引的一部分 我知道此时我可能会吹毛求疵 但是我想第一次就把这件事做好 而且我知道有时原始
  • F# 静态成员类型约束

    我正在尝试定义一个函数 factorize 它使用类似于 Seq sum 的结构类型约束 需要静态成员 Zero One 和 以便它可以与 int long bigint 等一起使用 似乎无法获得正确的语法 并且无法找到有关该主题的大量资源
  • 将数据类型 varchar 转换为 int 时出错

    我试图使用基于 varchar 类型的 Name 列的输入值的存储过程返回 item 表的 ItemId 列值 但是每当我将任何值传递给存储过程时 它都会返回一个错误 将数据类型 varchar 转换为 int 时出错 create pro
  • SQL 中的链表

    在 MySQL 数据库中存储链接列表的最佳方法是什么 这样插入就很简单 即 您不必每次都重新索引一堆内容 并且可以轻松地按顺序拉出列表 使用 Adrian 的解决方案 但不是增加 1 而是增加 10 甚至 100 然后可以按照要插入的内容之
  • MYSQL从另一个表插入id

    我有以下疑问 我有 2 张桌子 id customers 1 alan 2 beth 3 john and id id customers value 1 1 bar 2 1 foo 3 2 baz 示例 我需要在第二个表中添加值 alfa
  • 如何在C中递归地找到另一个字符串中的字符串位置?

    我们有一个任务来创建带有两个字符串参数的递归函数 原型应该是这样的 int instring char word char sentence 如果我们愿意调用函数 instring Word Another Word 它应该具有以下返回值
  • Spark 在执行 jdbc 保存时给出空指针异常

    您好 当我执行以下代码行时 我得到以下堆栈跟踪 transactionDF write format jdbc option url SqlServerUri option driver driver option dbtable full

随机推荐