2014-01-25 107 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;