Oracle 11G中的LIMIT/OFFSET

问题描述:

我正在尝试更新Oracle中的表,并且遇到了一些困难。我正在从MySQL迁移我的代码,并且MySQL允许的一些命令在Oracle中不受支持。Oracle 11G中的LIMIT/OFFSET

这里是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偏移量X命令。

问题如下。 Oracle不支持“限制”或“偏移量”命令。有关使用rownum和嵌套查询的限制问题的解决方法,但Oracle 11G解析器不喜欢它们在UPDATE命令中。

我有一个类似的问题,我需要一个更新命令内的限制,但不是一个偏移量。在这里解决了这个问题:MySQL to Oracle Syntax Error (Limit/Offset/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 

此变通办法可以让我的顶部或底部入口(通过使用ASC或DESC在DENSE_RANK命令),但我不能够找到一个代理偏移命令,如果我想在第二或第三排。

我试过的另一种解决方案是使用嵌套查询。第一行使用rownum命令得到前5行,以相反的方式排序,最后4行是MINUS-ed。此解决方案失败是因为Oracle解析器不理解对其中一个嵌套查询中引用的最外层命令中的表的引用。

(同样的问题,因为我是之前有:MySQL to Oracle Syntax Error (Limit/Offset/Update)

所面临的挑战不只是运行在Oracle中的SELECT语句的限制和偏移,因为我已经可以做到通过嵌套查询。挑战是让select语句在update语句中工作,因为即使语句在语法上是正确的,Oracle解析器也无法解码它们。到目前为止,嵌套查询(和谷歌)让我失望。

有没有其他人有类似的问题?

+1

如果升级到12C,你也许可以做到像'更新table1的T1组C5 =(从表2 T2选择ContractID其中t1.assetid = t2.assetid和t1.lastdate> = t2.lastdate和t1.firstdate = t2.firstdate order by lastdate asc offset 4取下1行);' – beldaz

+0

相关,如果您有Oracle 12cR1(或更高版本):http://stackoverflow.com/a/26051830/1461424 – Krumia

删除原来的答案,而不是可行

我觉得这应该是一个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; 
+0

没有。嵌套查询具有我前面提到的确切问题。最内层的查询不理解ALF是什么,即使它在最外层查询中指定。 SQL错误:ORA-00904:“ALF”。“ASSETID”:无效标识 – Brian

+0

@Brian - 对不起,当然你是对的。我似乎总是忘记这个问题,直到我真正遇到它。 –

+0

我并不完全确定代码的作用,但我已经使用您所展示的概念提出了一个解决方案。 (LEAD函数和使用存储过程) 基本上,我使用了一个存储过程,遍历表中的每个条目,使用rownumber作为索引。它搜索assetid =该行的assetid命令它,并使用lead函数获取下一个合约。 我猜解决方案的目的是使用存储过程。 – Brian