【问题标题】:LIMIT / OFFSET in Oracle 11GOracle 11G 中的限制/偏移
【发布时间】:2011-11-11 17:12:01
【问题描述】:

我正在尝试更新 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 排序,我只想要一个特定的,因此是 limit 1 offset X 命令。

问题如下。 Oracle 不支持“limit”或“offset”命令。使用 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

此解决方法允许我获取顶部或底部条目(通过在 dense_rank 命令中使用 asc 或 desc),但如果我想要第二行或第三行,我无法找到 offset 命令的代理。

我尝试过的另一个解决方案是使用嵌套查询。第一个使用 rownum 命令获取前 5 行,以相反的方式对它们进行排序,最后四行减去 MINUS。此解决方案失败,因为 Oracle 解析器不理解对嵌套查询中引用的最外层命令中的表的引用。

(和我之前遇到的问题一样:MySQL to Oracle Syntax Error (Limit / Offset / Update)

挑战不仅仅是在 oracle 中运行带有限制和偏移量的 select 语句,因为我已经可以通过嵌套查询来做到这一点。挑战在于让 select 语句在更新语句中工作,因为即使该语句在语法上是正确的,Oracle 解析器也无法解码它们。到目前为止,嵌套查询(和 Google)都让我失望了。

有没有其他人遇到过类似的问题?

【问题讨论】:

  • 如果你升级到 12c,你也许可以做类似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 offset 4 fetch next 1 row only);
  • 相关的,如果你有 Oracle 12cR1(或更高版本)可能有用:stackoverflow.com/a/26051830/1461424

标签: mysql sql oracle oracle11g offset


【解决方案1】:

已删除原始答案,不可行

我觉得这在单个 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;

【讨论】:

  • 不。嵌套查询有我之前提到的确切问题。最里面的查询不理解 ALF 是什么,即使它是在最外面的查询中指定的。 SQL 错误: ORA-00904: "ALF"."ASSETID": 标识符无效
  • @Brian -- 抱歉,你当然是对的。在我真正遇到它之前,我似乎总是忘记这个问题。
  • 我不确定代码的作用,但我已经使用您展示的概念提出了一个解决方案。 (LEAD 函数并使用存储过程) 基本上,我使用了一个存储过程,它使用 rownumber 作为索引来遍历表中的每个条目。它搜索assetid = 该行的assetid 对其进行排序,并使用lead 函数获取下一个合约。我想解决方案的要点是使用存储过程。
猜你喜欢
  • 2016-04-04
  • 2020-01-23
  • 1970-01-01
  • 2019-06-06
  • 2015-01-21
  • 2017-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多