如何使用Oracle中的连接从一个表中删除数据?

时间:2015-08-17 12:28:18

标签: oracle oracle11g delete-row

我正在尝试从一个具有连接条件的表中删除数据。

我试过这个

Delete test_one from test_one Val 
                join test_two En  
                  on Val.Map_Fromphyid=En.Fromphyid And            
                     Val.Map_Tophyid=En.Tophyid     And 
                     Val.Map_Relname=En.Relname 
                  Where Val.Result='NOT Done'

但是这给了我这个错误

  

“SQL命令未正确结束”

我知道我可以通过这种方式做到这一点

Delete From test_one 
       Where Phyid In (Select Val.Phyid From test_one Val 
                                        join test_two En  
                                        on Val.Map_Fromphyid=En.Fromphyid And
                                           Val.Map_Tophyid=En.Tophyid And 
                                           Val.Map_Relname=En.Relname 
                                        Where Val.Result='NOT Done');

第一种方法有什么问题?如果在没有子查询的情况下如何实现这一点是错误的?

我见过这个question。我正在寻找没有任何子查询的查询。我只用子查询找到答案。

2 个答案:

答案 0 :(得分:6)

您正在动态创建视图(即,而不是从您从查询delete from t获取的记录中删除要删除的表delete from <query>

要从这样的临时视图中进行选择,您需要使用parantheses(例如select * from (select from b)而不是select * from select from b

使用UPDATE语句它是一样的。所以要么从表中删除:

delete [from] test_one where ...

或从视图

delete [from] (select * from test_one ...)
但是不要忘记括号。并且不要将表格命名为

delete [from] test_one [from] (select * from test_one ...)

这就是你在做什么。

我觉得最好在可能的情况下直接从表中删除,因为在Oracle中删除临时视图对我来说似乎有点模糊,我认为这种可读性较差:

  • delete from (select * from a join b on a.x = b.x)
  • 删除
  • delete from (select * from b join a on a.x = b.x)从b
  • 删除
  • delete from (select a.* from b join a on a.x = b.x)
  • 删除

至少在我的Oracle版本中发生的是11g。

关于你的DELETE语句,我建议你这样写:

delete from test_one val 
where result = 'NOT Done'
and exists
(
  select *
  from test_two en  
  where en.fromphyid = val.map_fromphyid 
  and en.tophyid = val.map_tophyid     
  and en.relname = val.map_relname 
);

我认为这是可读的:删除所有&#39; NOT Done&#39;来自表test_one的记录,其中还存在表test_two中的条目。

答案 1 :(得分:2)

您可以在Oracle.

中使用Merge命令
Merge into test_one val
Using test_two en
on (
    Val.Map_Fromphyid = En.Fromphyid And
    Val.Map_Tophyid   = En.Tophyid And
    Val.Map_Relname   = En.Relname  
)
WHEN MATCHED THEN
DELETE WHERE Val.Result = 'NOT Done';