关于mysql:Oracle 11G中的LIMIT / OFFSET

LIMIT / OFFSET in Oracle 11G

我正在尝试更新Oracle中的表,但遇到了一些困难。我正在从MySQL移植代码,Oracle不支持MySQL允许的某些命令。

这是mysql代码:

1
2
3
 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);

子查询返回按lastdate排序的收缩列表,我只需要一个特定的收缩,因此使用limit 1 offset x命令。

问题如下。Oracle不支持"limit"或"offset"命令。使用rownum和嵌套查询可以解决限制问题,但Oracle11g解析器不喜欢在更新命令中使用它们。

我以前也遇到过类似的问题,在更新命令中需要一个限制,但不是偏移量。这里解决了:mysql到oracle语法错误(limit/offset/update)

Florin Ghita使用分析函数找到了一个解决方法。

1
2
3
4
5
6
7
8
 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),但是如果我想要第二行或第三行,我找不到offset命令的代理。

我尝试的另一个解决方案使用了嵌套查询。第一行使用rownum命令得到前5行,按相反的顺序排列,减去后4行。此解决方案失败,因为Oracle分析程序不理解对某个嵌套查询中引用的最外层命令中的表的引用。

(和以前一样的问题:mysql到oracle语法错误(limit/offset/update))

挑战不仅仅是在Oracle中运行带有限制和偏移量的select语句,因为我已经可以通过嵌套查询来实现这一点。挑战是让select语句在update语句中工作,因为即使语句语法正确,Oracle解析器也无法对其进行解码。到目前为止,嵌套查询(和Google)使我失败了。

其他人也有类似的问题吗?


已删除原始答案,不可行

我觉得在一条SQL语句中应该可以做到这一点,但是到目前为止,对相关子查询的需求和对某种分析函数的需求的结合使得我所尝试的一切都失败了。

下面是一个程序方法,我认为它可以满足您的需要:

1
2
3
4
5
6
7
8
9
10
11
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;