我在 ORACLE SGBD
上执行此查询service
执行此查询我收到此错误:
update product p set p.PROVIDER_ID =
( select PROVIDER_ID from provider pr where pr.VALID_FROM is not null
and ((pr.VALID_TO is not null and pr.VALID_TO < p.VALID_TO )
or (pr.VALID_TO is null and pr.VALID_FROM < p.VALID_TO) )
and rownum < 2 order by valid_to desc
)
where p.VALID_FROM is not null and p.VALID_TO is not null;
此时我被阻止了。
答案 0 :(得分:1)
这几乎是this的重复,因为直接的问题是你在子查询中有一个order by
子句 - 这是不允许的并且导致了这个错误。 Oracle希望在rownum < 2
之后看到子查询的右括号。
但在这种情况下,它会稍微复杂一点,因为您需要按顺序获取所需的行以进行匹配,并且您在错误的位置进行了rownum
检查;即使是一个独立的查询,它也不会给你你期望的结果,因为它会找到一个不确定的行然后命令那一行,这是没有意义的。
您需要另一个图层,因此您的子查询具有可以排序的内联视图,然后您从该第一行获取:
update product p set p.PROVIDER_ID =
(
select PROVIDER_ID from (
select pr.PROVIDER_ID from provider pr
where pr.VALID_FROM is not null
and ((pr.VALID_TO is not null and pr.VALID_TO < p.VALID_TO)
or (pr.VALID_TO is null and pr.VALID_FROM < p.VALID_TO))
order by pr.VALID_TO desc
)
where rownum < 2
)
where p.VALID_FROM is not null and p.VALID_TO is not null;
但现在您将获得ORA-00904: "P"."VALID_TO": invalid identifier
因为您尝试通过引用p
别名中的两个级别的列来关联更新,Oracle不允许这样做
另一种方法是使用分析,例如keep dense_rank
:
update product p set p.PROVIDER_ID =
(
select max(pr.PROVIDER_ID) keep (dense_rank first order by pr.VALID_TO desc)
from provider pr
where pr.VALID_FROM is not null
and ((pr.VALID_TO is not null and pr.VALID_TO < p.VALID_TO)
or (pr.VALID_TO is null and pr.VALID_FROM < p.VALID_TO))
)
where p.VALID_FROM is not null and p.VALID_TO is not null;
...确实成功运行。 (我不完全确定你的日期比较逻辑,但这是一个单独的问题,实际上可能就是你想要的。)