SQL - 从复杂查询更新 Oracle 10g 数据库

Posted

技术标签:

【中文标题】SQL - 从复杂查询更新 Oracle 10g 数据库【英文标题】:SQL - updating Oracle 10g database from a complex query 【发布时间】:2014-06-17 16:52:16 【问题描述】:

尝试根据条件更新单个列。查询返回需要更新的行

SELECT 
it.objectid,
it.versionnumber,
it.itemnumber "Item Number", 
it.itemtype,
itcovprem.basisofsettlement,
itcovprem.coverage "Coverage"
FROM 
itemcoveragesandpremiums itcovprem,
items it,
policies pl
WHERE 
pl.objectid = it.parentobjectid AND 
pl.policytype in ('H','F') AND
it.objectid = itcovprem.itemobjectid AND
it.itemtype in ('SHOA','SHOB','SHOC','SHOD','SHOK','SHOL') and
it.versionnumber = itcovprem.itemversionnumber AND
((itcovprem.coverage like ('A - Dwg Bldg%')) or
(itcovprem.coverage like ('#42 - Repl Cost Plus%')) or
(itcovprem.coverage like ('#42 - Limited GRC%'))) and
it.effectivedate >= TO_DATE('01-JAN-2006', 'DD-MON-YYYY') and
exists (select * from itemcoveragesandpremiums icp where icp.itemobjectid = it.objectid and icp.itemversionnumber = it.versionnumber and icp.coverage like ('#42%')) and
itcovprem.basisofsettlement not in ('LGRC')

我尝试了一些选项来将其转换为更新查询,但没有任何乐趣。

我收到错误 - 第 3 行 - 使用时 SQL 命令未正确结束

update itemcoveragesandpremiums
set basisofsettlement = 'LGRC'
from itemcoveragesandpremiums as itcovprem
inner join items as it
on it.objectid = itcovprem.itemobjectid and it.versionnumber = itcovprem.itemversionnumber
inner join policies as pl
on pl.objectid = it.parentobjectid 
where [cut, rest of query was below]

尝试使用内联查询时出现错误 - 第 6 行 - 缺少右括号

update
(
SELECT 
itcovprem.basisofsettlement as OLD
FROM 
itemcoveragesandpremiums as itcovprem inner join items as it on it.objectid = itcovprem.itemobjectid and it.versionnumber = itcovprem.itemversionnumber inner join policies AS pl on pl.objectid = it.parentobjectid 
WHERE [query snipped]
) t
set t.old = 'LGRC'

似乎 SQL*Plus 只是想在更新到达我的选择查询的内容之前停止查看更新。我不确定我的格式是否错误或从错误的方向进行。有什么建议吗?

【问题讨论】:

除非自我的“Oracle 时代”以来有所改变,否则 Oracle 不支持 UPDATE 语句中的 JOIN。 最后一个是因为不能用as给表名取别名;它仅对别名列名有效。这里解析器将as 视为别名,然后不知道如何处理itcovprem。但无论如何,带有连接的内联视图不太可能是可更新的。 您可能想查看这篇较早的帖子,看看是否有任何方法适合您。 【参考方案1】:

在您的第一次尝试中,第 3 行的错误是因为 update 不支持 fromjoin 子句。在您的第二次尝试中,第 6 行的直接错误是因为您尝试使用 as itcovprem 为表命名;但是you can only use as for column aliases, not for table aliases。 (第一次尝试也尝试这样做,但还没有遇到这个问题)。但是无论如何您通常都不能使用连接更新内联视图,因此它仍然会出错 - 类似于 ORA-01779。

您需要执行以下操作:

update itemcoveragesandpremiums
set basisofsettlement = 'LGRC'
where (itemobjectid, itemversionnumber, basisofsettlement, coverage) in (
  select it.objectid,
    it.versionnumber,
    itcovprem.basisofsettlement,
    itcovprem.coverage
  from ...
)

假设itemobjectid, itemversionnumber, basisofsettlement, coverage 充分识别了一行,这样您就不会冒险更新任何不应该更新的内容。将rowid 添加到选择中并将其用于更新以避免歧义可能会更安全:

update itemcoveragesandpremiums
set basisofsettlement = 'LGRC'
where rowid in (
  select itcovprem.rowid as target_rowid
  from ...
)

【讨论】:

谢谢亚历克斯,我很快就会深入研究这个。非常感谢!

以上是关于SQL - 从复杂查询更新 Oracle 10g 数据库的主要内容,如果未能解决你的问题,请参考以下文章

在 oracle 10g 中更新查询需要很长时间

如何在 java 中使用 jdbc 为 oracle 10g 执行 log miner PL/SQL 查询

oracle 10G数据库如何插入clob字段的值的简单语句sql语句

oracle 10g中怎样执行很长的sql语句呢(最长可能有10万+字符)

从 Oracle 10g 检索 CLOB 时出错

Oracle 数据库 10g 和 11g 中选择更新 ...的区别