2012-07-27 77 views
6

我目前正在写更新语句,以保持可查询表不断最新之间的Oracle SQL更新。该模式是两个表之间的相同和内容并不重要:基于子查询两个表

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更新“新”数据?

UPDATE

所以我临时数据可能凑巧反映的是在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”

+0

是否要在** PRODUCTION **表中保留** name **和** count **以及** STAGING **表正在更改? – hmmftg 2012-07-27 17:39:56

+0

为什么不使用触发器插入新值而不是此更新?这个更新究竟做了什么? – hmmftg 2012-07-27 17:42:22

+0

同意,在同步表格时,触发器对于保持实时更新非常有用。只需要注意表格错误的变异,并确保将其作为AFTER INSERT或UPDATE来执行。 – Hermit 2012-07-27 17:45:36

回答

26

有两种方法可以做到你正在尝试

一个是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

+0

让我试试多列相关。我不得不摆脱合并,因为它很慢(超过1000万条记录) – Woot4Moo 2012-07-27 18:35:25

0

正如你已经注意到了,你没有选择你的更新语句,以便它更新您的整个表。如果你想更新特定的行(例如,ID匹配的地方),你可能想做一个协调的子查询。

然而,由于您使用的是Oracle,它可能是更容易地创建一个物化视图为您查询表,并让Oracle的事务处理机制的细节。 MV的工作完全一样的语义查询表,是很容易成立,并允许您指定的刷新间隔。

1

没有上演,这是一个在黑暗中拍摄的数据集的例子,但你有没有尝试过这样的事情?

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

这会工作,假设id列在两个表上匹配。

+0

那么,如果我想匹配的唯一东西是我的子查询中的where子句呢? IE设置等等,其中p.name = s.name和p.count = s.count? – Woot4Moo 2012-07-27 17:50:29

+0

如果你这样做了,你会设置a = to b where a is = to b(即它什么也不做)。 – Hermit 2012-07-27 18:09:59

+0

哎呀失败的逻辑我的部分:) – Woot4Moo 2012-07-27 18:19:23

0

试试吧..
更新生产一个
SET(名称,计数)=(
SELECT姓名,计数
FROM STAGING b
WHERE a.ID = b.ID)
WHERE EXISTS(SELECT 1
FROM STAGING b
WHERE a.ID = b.ID
);