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 表中的 name 和 count 保持最新和 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 子句访问主表字段的子查询