【问题标题】:Dynamically delete rows from parent table after deleting rows from multiple child table从多个子表中删除行后从父表中动态删除行
【发布时间】:2021-12-09 09:42:45
【问题描述】:

我有一个脚本,它将返回父表和子表的详细信息以及相应的键列以及表行的删除顺序。 下面是脚本返回的详细信息:

| Child_table| Child_column| Parent_Table| Parent_Column| Delete_Order|
|:-----------|:------------| ------------| -------------|-------------|
| Child1     | Child1_ID   | Child2      | Child2_Id    |  2          |
| Child2     | Child2_ID1  | Parent1     | Parent_ID    |  1          |
| Child3     | Child3_ID   | Parent1     | Parent_ID    |  1          |
| Parent1    | Parent_ID   |             |              |  0          |

上表中,Child1Child2Child2@987654325的子表@Parent1 的子表。现在我需要按照Delete_Order 列中给出的降序删除从子表到父表的数据。

我需要帮助来编写一个动态查询来连接这些表和 根据主键数据删除 Child 和 Parent 表中的数据 来自父表。

【问题讨论】:

  • “我需要帮助”不是问题。您显然知道这涉及动态 sql,因此我建议您从以正确顺序在表上运行的游标开始。但是我怀疑这里缺少一些东西。您是否打算从这些表中删除所有行?
  • 你试过什么?请粘贴您的代码,我们将为您提供帮助。请选择好你的标签,你选择了“mysql”和“sql-server”......哪个是真正的?
  • 缺少参考 (FK) 列信息。
  • @SMor 是的,我正在使用动态查询,而不是使用游标,我正在尝试 while 循环。是的,我正在删除所有行。
  • @Carlos 我正在尝试但不确定如何动态加入这些多个表。它适用于 sql-server,因此我删除了 my-sql。谢谢

标签: sql sql-server dynamic-sql


【解决方案1】:

使用递归 CTE 创建 DELETE 语句。语句必须以do desc 的顺序运行。将 '=1' 替换为适当的值。

with cte as (
    select cast('delete' + x.childAlias + ' from ' + Child_table + x.childAlias +
           case when Parent_Column is null then ' where ' + Child_column + ' = 1;' else '' end as nvarchar(max))  sql,
        x.childAlias, Child_column, 
        Parent_Table, Parent_Column, 
        Delete_Order do
    from tbl
    cross apply (select ' t' + cast(tbl.Delete_Order as varchar(3))) x(childAlias)
    
    union all
    
    select cte.sql + ' join ' + tbl.Child_table + x.childAlias + 
           ' on' + cte.childAlias+ '.' + cte.Child_column + ' =' + x.childAlias + '.'+ cte.Parent_Column +
           case when tbl.Parent_Column is null then ' where' + x.childAlias + '.' + tbl.Child_column + ' = 1;' else '' end  sql,
        x.childAlias, tbl.Child_column,
        tbl.Parent_Table, tbl.Parent_Column,
        do  
    from cte
    join tbl on cte.Parent_Table = tbl.Child_table
    cross apply (select ' t' + cast(tbl.Delete_Order as varchar(3))) x(childAlias)
 ) 
 select sql, do
 from cte
 where sql like '%where%'
 order by do desc

db<>fiddle

【讨论】:

  • 问题是第一个 CTE 会给你父信息,因为给定的条件是 parent_column 为 null 并且 "=1" 中可能有什么值?试图理解这里的逻辑。
  • 将“1”替换为Parent1 表中要删除的行的Parent_ID 值及其所有子代。
  • 这里写的查询格式是否正确? cast('delete' + x.childAlias + ' from ' + Child_table + x.childAlias + case when Parent_Column is null then ' where ' + Child_column + ' = 1;' else '' end as nvarchar(max)) sql, x.childAlias, Child_column, Parent_Table, Parent_Column, Delete_Order do from tbl cross apply (select ' t' + cast(tbl.Delete_Order as varchar(3))) x(childAlias) 。此查询在表名之后有大小写,并且 x.ChildAlias 在中间没有位置。你能详细解释一下吗?
  • @SqlProgrammer,添加了小提琴。您可以逐步尝试,看看发生了什么。
  • 做了一些调整,它正在工作。谢谢
猜你喜欢
  • 2023-03-04
  • 1970-01-01
  • 2018-03-12
  • 1970-01-01
  • 2019-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多