Oracle SQL更新基于两个表之间的子查询

时间:2012-07-27 17:33:36

标签: sql oracle

我目前正在编写更新语句,以使可查询表始终保持最新状态。两个表之间的模式相同,内容并不重要:

STAGING  

ID  
NAME  
COUNT    

PRODUCTION  

ID  
NAME  
COUNT

我的更新语句如下所示:

update PRODUCTION  
set name = (select stage.name from staging stage where stage.name=name  and rownum <2),  
    count =   (select stage.countfrom staging stage where stage.count=count  and rownum <2);

需要注意的两点是:1)在更新结束时没有where子句(这可能是问题)和2)更新后的所有记录都具有相同的值。我的意思是:

BEFORE UPDATE:  

1,"JOHN", 12;  
2,"STEVE",15;  
3,"BETTY",2;  

AFTER UPDATE  

    1,"JOHN", 12;  
    2,"JOHN",12;  
    3,"JOHN",12;

我的问题是我该如何解决这个问题,以便表格正确反映来自登台的“新”数据作为正确的SQL更新?

更新

因此,我的暂存数据可能会巧合地反映PRODUCTION中的内容,为了便于讨论,它将会:

STAGING DATA TO MERGE:  

    1,"JOHN", 12;  
    2,"STEVE",15;  
    3,"BETTY",2; 

更新第二个

我想要运行的查询是:

update PRODUCTION
set production.name = staging.name,  
    production.count = staging.count

where production.name = staging.name;

然而,这会导致“staging.name”无效的标识符问题

4 个答案:

答案 0 :(得分:33)

有两种方法可以做你正在尝试的事情

一个是Multi-column Correlated Update

UPDATE PRODUCTION a
SET (name, count) = (
  SELECT name, count
  FROM STAGING b
  WHERE a.ID = b.ID);

DEMO

您可以使用merge

MERGE INTO PRODUCTION a
USING ( select id, name, count 
          from STAGING ) b
ON ( a.id = b.id )
WHEN MATCHED THEN 
UPDATE SET  a.name = b.name,
            a.count = b.count

DEMO

答案 1 :(得分:2)

试试..

UPDATE PRODUCTION a
SET (name, count) = (
SELECT name, count
        FROM STAGING b
        WHERE a.ID = b.ID)
WHERE EXISTS (SELECT 1
    FROM STAGING b
    WHERE a.ID=b.ID
 );

答案 2 :(得分:1)

如果没有分段数据集的例子,这是一个黑暗的镜头,但你尝试过这样的事情吗?

update PRODUCTION p,
       staging s
set p.name = s.name  
    p.count = s.count
where p.id = s.id

假设id列在两个表上匹配,这将起作用。

答案 3 :(得分:0)

正如您所注意到的,您对更新语句没有选择性,因此它会更新整个表。如果要更新特定行(即ID匹配的位置),您可能希望执行协调的子查询。

但是,由于您使用的是Oracle,因此可能更容易为查询表创建实例化视图,并让Oracle的事务机制处理详细信息。 MV的工作方式与查询语义的表完全相同,设置起来非常简单,并允许您指定刷新间隔。