【问题标题】:Delete rows from a left join从左连接中删除行
【发布时间】:2019-05-30 21:30:23
【问题描述】:

我想加入两个表并从中删除。

表1:

|ID| DATA|

表2:

|ID | ID_TAB1|

查询如下所示:

delete from table2 
using table2 as t2 left join table1 as t1 
on t2.ID_TAB1=t1.ID 
where t1.DATA='xxx';

问题是还有第三张表:

表3:

|ID|ID_TAB2|

当我运行我的语句时它失败了

表 table2 的更新或删除违反了表 table3 的外键约束

我确定 table3 中没有数据连接到带有t1.DATA='xxx' 的行,那么为什么会出现此错误?我的查询不正确吗?

【问题讨论】:

  • 先尝试删除外键约束,然后运行delete语句
  • 但我需要那里的约束。另外我有一个充满数据的大数据库,我现在不想重建它。
  • 当我只删除没有连接的单行时,它可以工作并且约束不是问题。
  • 这个错误听起来像是第三个表指向一个或多个正在被删除的记录。你确定不是这样吗?
  • 是的,我确定。第三个表中没有记录为真 t1.DATA='xxx'

标签: sql postgresql left-join sql-delete


【解决方案1】:

这个查询:

delete from table2 
using table2 as t2 left join table1 as t1 
on t2.ID_TAB1=t1.ID 
where t1.DATA='xxx';

实际上是从table2 中删除所有行(如果where 中没有匹配项,则删除所有行。t2table2 之间没有任何联系,因此这本质上是一个交叉连接。

正如documentation 中解释的(深入):

不要在 using_list 中重复目标表,除非您希望设置自联接。

大概是删除所有行导致第三个表出现问题。请注意,您确实要删除的行也可能导致问题。在这种情况下,您需要使用某种级联逻辑来处理错误。

您可以使用using 子句并删除join 来表达这一点:

delete from table2 t2
    using table1 t1 
    where t2.ID_TAB1 = t1.ID  and
          t1.DATA = 'xxx';

或者,只需在where 子句中使用exists

delete from table2 t2
    where exists (select 1
                  from table1 t1
                  where t1.id = t2.id_tab1 and t1.data = 'xxx'
                 );

【讨论】:

    【解决方案2】:

    你的意思可能是:

    delete from table2 
     using table1
    where  table2.ID_TAB1=table1.ID 
      and  table1.DATA='xxx';
    

    它与您的查询有何不同:

    • 它不会重新引入第二个独立的 table2 实例。否则,查询将删除 table2 中的所有行。

    • 连接的left 限定条件被滥用。左连接的要点是包含来自table2 的行,这些行没有对应的table1.id,缺少的table1 列设置为NULL。但条件t1.DATA='xxx' 与此相矛盾。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-14
      • 1970-01-01
      • 1970-01-01
      • 2016-08-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多