Sql 如何使用CTE和内部联接删除行?

Sql 如何使用CTE和内部联接删除行?,sql,oracle,common-table-expression,delete-row,sql-delete,Sql,Oracle,Common Table Expression,Delete Row,Sql Delete,如何使用CTE和内部联接从表中删除数据?这是有效的语法,因此应该这样做: with my_cte as ( select distinct var1, var2 from table_a ) delete from table_b b inner join my_cte on var1 = b.datecol and var2 = b.mycol; 在Oracle中,CTE和内部联接对DELETE命令都无效。这同样适用于INSERT和UPDATE命令 一般来说,最好的选择是使用DEL

如何使用CTE和内部联接从表中删除数据?这是有效的语法,因此应该这样做:

with my_cte as (
select distinct var1, var2
from table_a
)
delete  
from table_b b inner join my_cte 
  on var1 = b.datecol and var2 = b.mycol;

在Oracle中,CTE和
内部联接对
DELETE
命令都无效。这同样适用于
INSERT
UPDATE
命令

一般来说,最好的选择是使用
DELETE。。。哪里在
中:

DELETE FROM table_b
WHERE (datecol,  mycol) IN (
  SELECT DISTINCT var1, var2 FROM table_a)
还可以从子查询的结果中删除。这一点在本手册中有所涵盖(尽管很轻)


附录另请参见@Gerrat的答案,该答案显示了如何在
DELETE…WHERE…IN
查询中使用CTE。有些情况下,这种方法比我的答案更有帮助。

尝试以下方法:-

delete from table_b b where exists (
with my_cte as (
select distinct var1, var2
from table_a
)
select 1 from my_cte a
  where a.var1 = b.datecol and a.var2 = b.mycol;

Ed的回答不正确,w.r.t.用CTE删除(插入和更新命令同上)。
不能使用内部联接,但可以将CTE与DELETE一起使用

以下内容在Oracle 9i+中有效:

DELETE FROM table_b WHERE (datecol, mycol) IN (
    WITH my_cte AS (
        SELECT DISTINCT var1, var2
        FROM table_a
    )
    SELECT var1, var2 from my_cte
);

这个特殊的案例根本不会从CTE中受益,但其他更复杂的语句可能会受益。

我必须通过引用其他两个表2和3来删除表1中的记录,所以:

DELETE
  FROM table1
 WHERE table1.var1 = :parameter1
   AND table1.var2 || table1.var3 IN
   (WITH my_cte
      AS (SELECT table2.var3
            FROM table2
           WHERE table2.var1 > :parameter2
             AND table2.var2 = constant1
             AND :parameter2 >= (SELECT
                                MAX(table3.var1)
                                   FROM table3
                                  WHERE
                                     table3.var2
                                   = table2.var3
                                   )
         )
    SELECT table3.var3 || table3.var4
            FROM table3
           INNER JOIN my_cte
              ON (table3.var2 = my_cte.var1)
   )
对于任何感兴趣的人,在SQLServer上,各个子句的顺序必须不同:

WITH my_cte
  AS (SELECT table2.var3
        FROM table2
       WHERE table2.var1 > :parameter2
         AND table2.var2 = constant1
     AND :parameter2 >= (SELECT MAX(table3.var1)
                           FROM table3
                          WHERE table3.var2
                                = table2.var3
                        )
     )
DELETE
  FROM table1
  WHERE table1.var1 = :parameter1
    AND table1.var2 || table1.var3 IN
        (SELECT table3.var3 || table3.var4
           FROM table3
          INNER JOIN my_cte
             ON (table3.var2 = my_cte.var1)
        )

子查询中的
distinct
是不需要的(这是
in
操作符中的
所暗示的),谢谢-我从来不知道这一点。我一直认为它可以通过限制子查询结果来优化,但我从来没有实际检查过执行计划以进行验证。今晚我会仔细看看这个。
DISTINCT
在我的查询中有什么害处吗?如果Oracle只是从子查询中删除了
DISTINCT
,我不会感到惊讶,所以我想从性能的角度来看这并不重要。我不知道Oracle是如何处理它的,但是从一个简单的逻辑角度来看,它相当于将
DISTINCT
隐式添加到子查询中。
运算符中的
检查使用某种哈希或树最快处理的包含关系。然后,碰撞可以在途中处理。非常好@Gerrat,谢谢你的发帖!我从来没想过这个。我同意,更复杂的语句将受益于这种构造。