从另一个表的不同列更新相同的列

时间:2016-08-20 06:21:18

标签: sql oracle11g

我使用以下3个查询根据另一个表中3个不同列的值更新状态。

UPDATE NUMBER_TABLE  SET STATUS='X'  WHERE STATUS='P' AND NUMBER IN 
            (SELECT NVL(CONTACT_NO,'XXXXXXXXXX') FROM TMP_NUMBER_FOUND WHERE STATUS='P');

UPDATE NUMBER_TABLE  SET STATUS='X'  WHERE  STATUS='P' AND NUMBER IN 
            (SELECT NVL(HOME_NO,'XXXXXXXXXX') FROM TMP_NUMBER_FOUND WHERE STATUS='P');

UPDATE NUMBER_TABLE  SET STATUS='X'  WHERE  STATUS='P' AND NUMBER IN 
            (SELECT NVL(WORK_NO,'XXXXXXXXXX') FROM TMP_NUMBER_FOUND WHERE STATUS='P');

所有3个查询都在进行全表扫描。有人可以建议一种更好的方法将3个查询合并为一个

3 个答案:

答案 0 :(得分:1)

这样的事情应该有效。

注意:您说您使用这三个查询进行更新......但事实并非如此。您的查询无法按书面形式运作; NUMBER是保留的Oracle关键字,因此您将收到编译错误。当你发帖时,请小心你说的话。出于同样的原因,我在下面提供的查询作为解决方案也不起作用。使用您的实际列名。

UPDATE NUMBER_TABLE n SET STATUS='X'  WHERE STATUS='P' AND EXISTS
   ( SELECT 1 FROM TMP_NUMBER_FOUND t where n.NUMBER = NVL(t.CONTACT_NO, 'XXXXXXXXXX')
                                      or    n.NUMBER = NVL(t.HOME_NO   , 'XXXXXXXXXX')
                                      or    n.NUMBER = NVL(t.WORK_NO   , 'XXXXXXXXXX')
   )
;

根据OP的更多信息添加(请参阅评论)。

OP分享了他的数据中没有数字等于'XXXXXXXXXX'的信息。在这种情况下,NVL(...)是不必要的,只会浪费时间。在这种情况下,与'XXXXXXXXXX'相比,与NULL的比较相同,因为与NULL相比,永远不会返回TRUE。所以:删除那些NVL包装,它们是缓慢的重要来源。

这将带来另一个更大的好处:如果列CONTACT_NOHOME_NOWORK_NO尚未被列入索引,并且它们未被{NVL(...)包围,则应对其进行索引{1}},实际上可以使用索引。 NUMBER上还应该有一个索引。 OP说这个专栏是PK的一部分,但不是PK中的第一列,并询问他是否应该把它作为第一列。答案是肯定的 - 或者,如果有充分的理由认为另一列应该保留在第一列(也许其他查询依赖于那个),那么NUMBER应该得到它自己的索引。但如果它可以成为PK中的第一列,那就足够了。

答案 1 :(得分:1)

您可以将CASE与更新结合使用,

UPDATE NUMBER_TABLE  SET STATUS=(CASE when NUMBER IN 
            (SELECT NVL(CONTACT_NO,'XXXXXXXXXX') FROM TMP_NUMBER_FOUND WHERE STATUS='P') AND STATUS='P' then 'X'  
            when NUMBER IN 
            (SELECT NVL(HOME_NO,'XXXXXXXXXX') FROM TMP_NUMBER_FOUND WHERE STATUS='P') AND STATUS='P' then 'X'
              WHEN NUMBER IN  
            (SELECT NVL(WORK_NO,'XXXXXXXXXX') FROM TMP_NUMBER_FOUND WHERE STATUS='P') AND STATUS='P' then 'X' ELSE STATUS END);

答案 2 :(得分:0)

我建议

UPDATE number_table n INNER JOIN tmp_number_found t
                              ON n.number = NVL(t.contact_no, 'XXXXXXXXXX')
                              OR n.number = NVL(t.home_no, 'XXXXXXXXXX')
                              OR n.number = NVL(t.work_no, 'XXXXXXXXXX')
   SET n.status='X'
 WHERE n.status='P'
   AND t.status='P'
;