2016-08-11 29 views
0

我见过很多答案,当表2中存在行时会更新表1,但没有一个在选择表中存在行时使用LEFT JOIN行(为了更好的性能)。我有一个更新的解决方案,但它会执行不好,因为它使用NOT IN。Oracle在表1中更新列时,当表2中不存在相关行时

因此,这个SQL将根据需要更新表,但在对大型表运行时使用起来非常昂贵。

update header 
set status='Z' 
where status='A' 
and header.id not in (
    select headerid 
    from detail 
    where detail.id between 0 and 9999999 
); 

现在我有使用LEFT JOIN返回正确的ID表现良好的查询,但我一直无法将其插入到一个更新语句给予同样的结果。 select语句是

select header.id 
from header 
left join detail on detail.headerid = header.id 
where detail.headerid is null 
and header.status='A' 

所以,如果我用这个更新语句,如:

update header 
set status = 'Z' 
where header.id = (
    select header.id 
    from header 
    left join detail on detail.headerid = header.id 
    where detail.headerid is null and header.status='A' 
) 

然后我会失败:

ORA-01427:单行子查询返回多行

我期待着他多ader.id被返回并且想要更新所有这些行。

因此,我仍然在寻找一种解决方案,它将更新返回的行,使用性能良好的SQL select来返回表头中的行,但在详细信息表中没有相关的行。

任何帮助,将不胜感激,否则我将留下性能不佳的更新。

回答

0

如你预期,你应该使用IN

试试这个

Update 
    header 
Set status = 'Z' 
Where 
    header.id IN (select 
         header.id 
        From 
         header 
        Left join 
         detail 
        On 
         detail.headerid = header.id 
        Where 
         detail.headerid is null 
        And 
         header.status='A') 
0

我不会把条件对既然你期望多个头ID &子查询返回多个ID子查询中的表。我更舒服写这个逻辑:

update header h 
    set status = 'Z' 
    where not exists (select 1 
         from detail d 
         where d.headerid = h.id 
        ) and 
      h.status = 'A'; 

如果性能是一个问题,在detail(headerid)header(status, id)和帮助索引。

0

典型的,我看了下一个地方,我找到了答案......

update header set status='Z' where not exists (select detail.headerid from detail where detail.headerid = header.id) and status = 'A' 

哦,好吧,至少它在这里,如果别人想找到它。

0

由于错误说明您的子查询返回多个行,并且您在更新查询中使用了=符号。 =符号是不允许的,如果您的查询返回多个记录使用IN,NOT IN,EXISTS,NOT EXISTS根据您的要求

相关问题