【问题标题】:DELETE FROM <subquery>删除 <子查询>
【发布时间】:2014-02-16 08:40:19
【问题描述】:
DELETE FROM (SELECT * FROM orders1 o,order_item1 i
WHERE i.order_id = o.order_id );

上面的查询没有特别提到删除行。而不是我提到了一个子查询。 但是这个查询执行没有任何错误,并删除了order_item1 表行。

oracle 服务器如何决定应该删除哪些表行? 为什么orders1表行不能删除?

【问题讨论】:

    标签: sql oracle oracle11g oracle10g


    【解决方案1】:

    在您的情况下,子查询的表 orders1 肯定有一个主键 (order_id) 和表order_item1 有对应的外键order_id

    因此,Oracle 将表 order_item1 转换为 键保留表,并且能够在外部 delete 语句中从该表中删除。

    key保留表的概念在This tahiti documentation link有进一步的解释。

    如果你想知道什么被删除了,你可以这样

    这些是在您的子查询中连接的表:

    create table tq84_orders1 (
       id     number primary key,
       col_1  varchar2(10),
       col_2  date
    );
    
    create table tq84_order_item1 (
      order_id references tq84_orders1,
      col_3    varchar2(10),
      col_4    date
    );
    

    此视图模拟子查询:

    create view tq84_orders_v as (
      select * 
      from
        tq84_orders1     o,
        tq84_order_item1 i
      where
        o.id = i.order_id
    );
    

    此查询(在 user_updateable_columns 上)现在查找哪些列实际被删除(或可以删除​​):

    select
      table_name,
      column_name,
    --updatable,
    --insertable,
      deletable
    from
      user_updatable_columns
    where
      table_name = 'TQ84_ORDERS_V';
    

    结果表明ORDER_ID、COL_3和COL_4这三列实际上可以删除,它们都源于TQ84_ORDER_ITEM1。

    TABLE_NAME                     COLUMN_NAME                    DEL
    ------------------------------ ------------------------------ ---
    TQ84_ORDERS_V                  ID                             NO
    TQ84_ORDERS_V                  COL_1                          NO
    TQ84_ORDERS_V                  COL_2                          NO
    TQ84_ORDERS_V                  ORDER_ID                       YES
    TQ84_ORDERS_V                  COL_3                          YES
    TQ84_ORDERS_V                  COL_4                          YES
    

    【讨论】:

    • 我以为它会触发ORA-01752: cannot delete from view without exactly one key-preserved table
    • @MaheswaranRavisankar:如果没有定义主键,您会收到此错误消息。
    • 另外提到,如果两个表都有主键,那么FROM子句中第一个指定的表将被删除!
    • @MaheswaranRavisankar:我假设如果使用现代显式JOINs 而不是过时的隐式连接,它将从from 子句中指定的表中删除,而不是@987654337 中的表@ 子句,对吗?
    • @a_horse_with_no_name 是的,这是有道理的。另一个证明现代语法概念的例子!
    【解决方案2】:

    这可能对你有帮助

    DELETE FROM orders1 o CROSS JOIN order_item1 i WHERE i.order_id = o.order_id

    【讨论】:

    • 这在 Oracle 中不起作用,因为它不允许在 DELETE 语句中加入。 (而且我绝对确定您不想从两个表的笛卡尔积中删除 - 即使您随后在 where 中使用过时的隐式连接语法将 cross join 转换为内部连接)
    【解决方案3】:

    我认为如果你想从just ONE 表中删除行,你可以使用这个查询:

    DELETE FROM orders1 WHERE order_id in 
    (SELECT o.order_id FROM orders1 o,order_item1 i
    WHERE i.order_id = o.order_id );
    

    但如果你想从两个表中删除行,你可以这样做:

    CREATE TABLE TEMP_TAB AS SELECT o.order_id FROM orders1 o,order_item1 i
    WHERE i.order_id = o.order_id;
    
    DELETE FROM order_item1 WHERE order_id in 
    (SELECT TEMP_TAB.order_id FROM TEMP_TAB);
    
    DELETE FROM orders1 WHERE order_id in 
    (SELECT TEMP_TAB.order_id FROM TEMP_TAB);
    
    DROP TABLE TEMP_TAB;
    

    【讨论】:

      【解决方案4】:

      我目前无权访问 Oracle 环境,因此无法验证,但以下内容在 SQL Server 中确实有效,并将从 Orders 表中删除。如果要从 Order_Item 中删除,请反转表。

      DELETE o
      FROM   Orders o
             JOIN Order_Item oi ON o.order_id = oi.order_id
      WHERE  [filter condition]
      

      【讨论】:

      • 不,这行不通。 Oracle 不允许在 delete 语句的 from 子句中进行连接。顺便说一句:这是一个 Oracle 环境:sqlfiddle.com
      【解决方案5】:

      在您的子查询中,您提供了“i.order_id = o.order_id”。您可以这样尝试

      DELETE FROM (SELECT * FROM orders1 o,order_item1 i WHERE o.order_id=i.order_id);

      这是正确的

      【讨论】:

      • 您的查询与使用的查询没有区别
      猜你喜欢
      • 2012-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多