2014-01-25 109 views
2
DELETE FROM (SELECT * FROM orders1 o,order_item1 i 
WHERE i.order_id = o.order_id); 

上面的查询没有提到特别要删除的rows.Instead我已经提到了一个子查询。 但是,此查询无任何错误地执行并删除order_item1表格行。删除从<subquery>

如何Oracle服务器决定哪个表行应该被删除? 为什么orders1表行无法删除?

回答

10

在你的情况下,子查询的表orders1有肯定主键 (order_id)和表order_item1有相应的外键order_id

因此,Oracle将表order_item1变为保存键的表,并且能够从该表中删除外部delete语句中的该表。

键保存表的概念在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 
); 

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

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 
+0

我认为它会触发'ORA-01752:不能从视图中删除没有一个键保存表。 –

+0

@MaheswaranRavisankar:如果没有定义主键,你会得到这个错误信息。 –

+1

+1 ..我学到了东西! [Demo](http://www.sqlfiddle.com/#!4/566ab/3) –

0

这可以帮助你

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

+2

这不会在Oracle中工作,因为它不允许在DELETE语句中进行连接。 (并且我绝对确信**不希望从两个表的笛卡尔积中删除 - 即使您随后使用过时的隐式连接语法将'cross join'变为内部连接) –

0

在你的子查询你给像 “i.order_id = o.order_id”。你可以尝试这样的

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

这将是正确的

+2

您的查询与已使用的查询之间没有区别 –

0

我没有在时刻访问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] 
+2

不,这不起作用。 Oracle不允许在'delete'语句的from子句中进行连接。顺便说一句:这里是一个Oracle环境:http://sqlfiddle.com –

0

我认为,如果你想从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;