【问题标题】:Oracle Delete Rows Matching On Multiple ValuesOracle删除与多个值匹配的行
【发布时间】:2009-02-02 17:28:28
【问题描述】:

我想做这样的事情:

DELETE FROM student WHERE
student.course, student.major IN
(SELECT schedule.course, schedule.major FROM schedule)

但是,您似乎只能将一列与 IN 运算符一起使用。真的吗?看起来像这样的查询应该是可能的。

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    不,你只需要括号:

    DELETE FROM student WHERE
    (student.course, student.major) IN
    (SELECT schedule.course, schedule.major FROM schedule)
    

    【讨论】:

    • 所以这实际上具有误导性,我认为它的非直觉性本质上是不正确的。如果您的行包含空值 IN 不起作用。我想,这对于 null 的含义是有意义的,但与例如减号的工作原理完全不一致。
    【解决方案2】:

    您也可以使用 EXISTS 子句:

    DELETE FROM student WHERE
    EXISTS
    (
      SELECT 1 FROM schedule 
      WHERE schedule.course=student.course 
      AND schedule.major=student.major
    )
    

    【讨论】:

    • +1; WHERE EXISTS 是一种被严重低估的机制,比使用 IN 要好得多
    • @Brian:(我意识到我回复你的评论有点晚了!)你为什么说 EXISTS 比 IN 好得多?
    • 一个很好的问题。我的理解是,在性能方面这是一个不错的选择,但在证据方面我提供的很少。也就是说,我设法找到了这个:techrepublic.com/article/…
    • 好吧,IN 子句中的结果值也有可能过多,我过去曾见过这会导致问题......比如超过 1024....
    【解决方案3】:
    DELETE FROM student WHERE
    (student.course, student.major) IN
    (SELECT schedule.course, schedule.major FROM schedule)
    

    在 where 子句中为您的条款加上括号。干杯!

    【讨论】:

      【解决方案4】:

      在 Oracle 中,您可以从内联视图中执行删除操作,但它通常需要一个外键来确保删除该行的表中的一行不能由视图中的多行表示.

      create table parent (id number primary key);
      create table child (id number primary key, parent_id number references parent);
      insert into parent values(1);
      insert into child values(2,1);
      delete from (select * from parent p, child c where c.parent_id = p.id);
      

      【讨论】:

        【解决方案5】:

        请注意,如果任何属性为空,则该行被认为不是 IN。也就是说,如果课程相同,并且学生和时间表专业都为空,则不会删除行。

        如果某个属性(例如major)可能为null,并且您希望null = null 为true,请尝试:

        DELETE
        FROM student
        WHERE (student.course, NVL(student.major,'sOmeStRinG') )
        IN (SELECT schedule.course, NVL(schedule.major,'sOmeStRinG') FROM schedule)
        

        【讨论】:

          【解决方案6】:

          下面的语法适用于 SQLServer 但我相信它是标准的 sql 但正如 cmets 中指出的,这是非标准实现,Oracle 目前不支持。

          留作参考

          delete s
          from 
              student s 
              inner join schedule sch
              on s.course=sch.course 
              and s.major = sch.major
          

          【讨论】:

          • 不,标准 SQL 只支持 DELETE 中的一张表。 MySQL 和 Microsoft SQL Server 支持多表 DELETE 作为标准的扩展,但 Oracle 不支持。
          • 表的 SQL 标准概念并不仅限于表。它通常包括视图。某些视图是可更新的,并且通过扩展,是可删除的。
          • 感谢 cmets,很高兴了解 DB 实现的差异。我已更新我的答案以包含您的观点
          猜你喜欢
          • 2014-09-19
          • 1970-01-01
          • 2021-05-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-09-30
          相关资源
          最近更新 更多