我正在尝试更新Oracle中的表,但遇到了一些困难。我正在从MySQL移植我的代码,Oracle不支持MySQL允许的某些命令。
这是MySQL代码:
update table1 t1 set c5 = (select ContractID from table2 t2 where t1.assetid = t2.assetid and t1.lastdate >= t2.lastdate and t1.firstdate= t2.firstdate order by lastdate asc limit 1 offset 4);
子查询返回一个ContractIDS列表,按lastdate排序,我只想要一个特定的列表,因此限制1 offset X命令。
问题如下。Oracle不支持“限制”或“偏移”命令。对于使用rownum和嵌套查询的限制问题,有一些解决方法,但是Oracle 11G解析器在UPDATE命令中不喜欢它们。
在需要更新命令中的限制(而不是偏移量)之前,我遇到了类似的问题。
Florin Ghita使用分析功能找到了一种解决方法。
update table1 alf set nextcontractid = (SELECT min(contractid) keep (dense_rank first order by lasttradedate asc) FROM table1copy alf2 WHERE alf2.assetid = alf.assetid AND alf2.lasttradedate > alf.lasttradedate ) where alf.complete = 0
此解决方法使我可以获取顶部或底部条目(通过在density_rank命令中使用asc或desc),但是如果需要第二行或第三行,则无法找到offset命令的代理。
我尝试过的另一种解决方案是使用嵌套查询。第一个使用rownum命令获得前5行,并以相反的方式对它们进行排序,将最后四行减掉MINUS。该解决方案失败了,因为Oracle解析器不理解在嵌套查询之一中引用的最外层命令中对表的引用。
挑战不只是在oracle中以限制和偏移量运行select语句,因为我已经可以通过嵌套查询做到这一点。挑战在于使select语句在update语句中工作,因为即使该语句在语法上是正确的,Oracle解析器也无法对它们进行解码。到目前为止,嵌套查询(和Google)使我失败了。
还有其他人遇到过类似的问题吗?
已删除原始答案,不可行
我认为这在单个SQL语句中应该是可行的,但是到目前为止,对相关子查询的需求与对某种解析函数的需求的结合使我尝试过的一切都失败了。
我认为这是一种程序方法,可以满足您的要求:
DECLARE CURSOR t IS SELECT LEAD(contractid,4) OVER (PARTITION BY assetid ORDER BY lasttradedate ASC) lead_contractid FROM table1 FOR UPDATE; BEGIN FOR r IN t LOOP UPDATE table1 SET nextcontractid = r.lead_contractid WHERE CURRENT OF t; END LOOP; END;