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

Posted

技术标签:

【中文标题】Oracle SQL 更新基于两个表之间的子查询【英文标题】:Oracle SQL update based on subquery between two tables 【发布时间】:2012-07-27 17:33:35 【问题描述】:

我目前正在编写更新语句以使可查询表不断更新。两个表之间的架构是相同的,内容并不重要:

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”出现无效标识符问题

【问题讨论】:

您想让 PRODUCTION 表中的 namecount 保持最新和 STAGING 表正在改变? 为什么不使用触发器来插入新值而不是这次更新?这次更新究竟做了什么? 同意,在同步表时,触发器对于保持它们实时更新非常有用。请注意变异表错误,并确保将其作为 AFTER INSERT OR UPDATE 执行。 @hmmftg 此更新只是为了从暂存中提取数据以使生产保持最新。类似于如何为现实生活中的示例更新天气报告。每 X 分钟左右 @Hermit 这很可能会成为触发器,我正在自己测试普通的sql。 【参考方案1】:

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

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

【讨论】:

让我试试多列关联。我不得不放弃合并,因为它很慢(超过 1000 万条记录)【参考方案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
 );

【讨论】:

【参考方案3】:

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

但是,由于您使用的是 Oracle,因此为查询表创建物化视图并让 Oracle 的事务机制处理细节可能会更容易。 MV 的工作方式与查询语义的表完全一样,非常容易设置,并且允许您指定刷新间隔。

【讨论】:

【参考方案4】:

如果没有 staging 数据集的示例,这是在黑暗中拍摄,但您是否尝试过类似的方法?

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

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

【讨论】:

如果我只想匹配子查询中的 where 子句怎么办? IE set blah where p.name=s.name and p.count=s.count? 如果你这样做了,你会将 a = 设置为 b,其中 a = = b(即它什么也不做)。 糟糕,我的逻辑失败了 :)

以上是关于Oracle SQL 更新基于两个表之间的子查询的主要内容,如果未能解决你的问题,请参考以下文章

Oracle SQL 中结合 LIMIT 子句访问主表字段的子查询

Oracle SQL - 多级相关子查询不起作用

使用带有更新 SQL 的子查询

使用两个可以返回多个值的子查询的 SQL 之间的语句

Oracle通过带有内部连接和返回n行的子查询的桥表选择查询?

FROM 中的子查询在 Oracle SQL 中不起作用