【问题标题】:Oracle, update column in table 1, when related row does not exist in table 2Oracle,当表2中不存在相关行时,更新表1中的列
【发布时间】:2016-08-11 10:43:18
【问题描述】:

我已经看到了许多答案,当表 2 中存在行时会更新表 1,但没有一个在选择行时使用 LEFT JOIN 的答案(以获得更好的性能)。我有一个更新的解决方案,但它会因为使用 NOT IN 而表现不佳。

因此,此 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 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: 单行子查询返回多于一行

我希望返回多个 header.id 并希望更新所有这些行。

所以我仍在寻找一种解决方案,该解决方案将更新返回的行,使用性能良好的 SQL 选择来返回表头中的行,而这些行在明细表中没有相关行。

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

【问题讨论】:

    标签: sql oracle sql-update left-join


    【解决方案1】:

    由于您期望多个标头 ID 并且子查询返回多个 ID,因此您应该使用 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')
    

    【讨论】:

      【解决方案2】:

      我不会将条件放在子查询中的 outer 表上。我更愿意将这个逻辑写成:

      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) 上建立索引并提供帮助。

      【讨论】:

        【解决方案3】:

        典型,下一个地方,我找到了答案……

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

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

        【讨论】:

          【解决方案4】:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2020-10-05
            • 1970-01-01
            • 2015-03-31
            • 2019-02-21
            • 2012-10-03
            • 2016-06-06
            • 1970-01-01
            相关资源
            最近更新 更多