Oracle 从多个表更新
Posted
技术标签:
【中文标题】Oracle 从多个表更新【英文标题】:Oracle update from multiple tables 【发布时间】:2015-04-28 22:30:42 【问题描述】:我有一个包含两个事实表和几个维度表的星型模式。我想将其中一个事实更新为两个事实表中事实的总和。假设我有如下数据:
Fact1:
Val1|Dim1|Dim2|Dim3|RunNB
100 |1 |2 |3 |1
200 |1 |2 |4 |1
101 |1 |2 |3 |2
Fact2:
Val2|Val3|Dim1|Dim2|Dim3|RunNB
100 |0 |1 |2 |3 |3
200 |0 |1 |2 |4 |3
101 |0 |1 |2 |3 |4
Run:
RunNB|Date
1 |20150423
2 |20150428
3 |20150423
我想用 Fact1.Val1 + Fact2.Val2 填充 Fact2.Val3,用于尺寸匹配的所有行,并且与运行关联的日期相同。
以下查询选择正确的数据:
select Fact1.Val1 + Fact2.Val2
from Fact1, Fact2, Run r1, Run r2
where Fact1.Dim1 = Fact2.Dim1 AND
Fact1.Dim2 = Fact2.Dim2 AND
Fact1.Dim3 = Fact3.Dim3 AND
Fact1.RunNB = r1.RunNB AND
r1.Date = '20150423' AND
Fact2.RunNB = r2.RunNB AND
r2.Date = '20150423';
我需要选择总和,然后用总和更新适当的 Fact2.Val3。我在构建更新语句时遇到问题。
我的理解是Oracle不支持:
update x
set y
FROM z
where q
我也试过了:
update (
select ...
) set ...
语法,但我无法正常工作。我可以为此使用 MERGE 吗?任何帮助将不胜感激。
【问题讨论】:
这似乎是一个糟糕的数据模型。具有两个事实表的星型模式不是真正的星型模式。但是两个具有相同维度和相关事实的事实表呢?绝对臭。此外,如果您的事实表包含适当的仓库卷,您不希望在它们上运行更新语句(包括合并)。 同意。我试图做的任务没有意义。但是,由于各种遗留原因,我需要这样做。我不能改变数据模型,也不能改变要求。您对我如何实现这一点有任何想法吗? 【参考方案1】:此merge
语句适用于给定示例:
merge into (select * from fact2
where runnb in (select runnb from run where rDate = '20150423')) f2
using (
select dim1, dim2, dim3, run.runnb, val1
from fact1 join run on fact1.runnb = run.runnb and rDate = '20150423' ) f1
on (f1.dim1 = f2.dim1 and f1.dim2 = f2.dim2 and f1.dim3 = f2.dim3)
when matched then update set f2.val3 = f1.val1 + f2.val2;
如果表 fact1 中的 dim1、dim2、dim3 一天的行数多于一行,则必须首先在 using
部分中对它们进行分组和求和,
否则可能会出现错误无法获得稳定的行集。
顺便说一句 - 我在表 run
中将 date
重命名为 rdate
。
【讨论】:
谢谢。当我实现这个时,我得到以下 Oracle 错误:Error report: SQL Error: ORA-30926: unable to get a stable set of rows in the source tables 30926. 00000 - "unable to get a stable set of rows in the source tables" *Cause: A stable set of rows could not be got because of large dml activity or a non-deterministic where clause. *Action: Remove any non-deterministic where clauses and reissue the dml.
我的真实数据集比我的示例中的大得多,但是两个 select 语句都返回相同数量的记录,没有欺骗。对这个问题有什么想法吗?
更新:我想我看到了 ORA-30926 错误的根本原因。由于数据的规范化存在一些问题,实际上存在一些欺骗(大约 160000 条记录中的 10 条)。我怀疑查询不会出现这些错误...谢谢。
正如我警告过的那样 - 此错误意味着对于某些行,fact1
中存在相同(dim1、dim2、dim3、日期)的重复项。这是SQLFiddle,我在其中重现了这种情况,您可以从小提琴中对您的数据运行查询以检查它。要使merge
正常运行,此查询不应返回任何行。我在fact1
中添加了一行,val1=201。现在merge
(我也不知道)不知道它必须使用哪一行。解决方案是在内部查询中对数据进行分组,但我不知道你是否想要这个。或者消除欺骗。以上是关于Oracle 从多个表更新的主要内容,如果未能解决你的问题,请参考以下文章
oracle 怎么理解update 表 set 字段1 = 值,字段2 = 值 where 字段3 = 值