【问题标题】:sqplus: Retrieve results in chunks (update ROWNUM in loop)sqlplus:以块的形式检索结果(在循环中更新 ROWNUM)
【发布时间】:2016-06-02 19:02:07
【问题描述】:

我对使用 sqlplus 很陌生,所以如果这是一个愚蠢的问题,我很抱歉。

我有一个很长的表单查询:

SELECT columnA 
from tableA 
where fieldA in (
  (select unique columnB
  from tableB
  where fieldB in 
    (select columnC
    from tableC
    where fieldC not in
      (select columnD 
      from tableD 
      where x=y 
      and a=b 
      and columnX in 
        (select columnE 
        from tableE
        where p=q)))
  and columnInTableB = <some value> 
  and anotherColumnInTableB = <some other value> 
  and thirdColumnInTableB IN (<set of values>) 
  and fourthColumnInTableB like <some string>); 

每个表大约有 15 - 30 列和不同数量的行。 TableB 是最大的,总共有大约 500 万行。表 A - E 各有 500,000 - 100 万行。

我尝试了几种方法:

1) 按原样运行此查询:

这个查询运行了很长时间,我得到了错误 - ORA-01555: 快照太旧: 回滚段号 名称为

我做了一些研究,发现如下: ORA-1555: snapshot too old: rollback segment number

但是,我没有更改撤消段的权限。

2) 我使用 with...as 重新编写了查询,但随后出现错误: 无法通过 在表空间 TEMP

中扩展临时段

再次,我找到了有关如何修复此错误的说明,但我没有扩展临时段的权限。

运行时间最长的查询是:

(select unique columnB
  from tableB  ...

在最坏的情况下,and fourthColumnInTableB like &lt;some string&gt;); 匹配表 B 中大约 300 万个条目。

有人建议我“以较小的块运行查询”。

我想到的一种方法是为长时间运行的子查询检索数据(

(select unique columnB
  from tableB  ...

)

以块为单位(按照建议使用 ROWNUM here。 我的问题是这样的:

我不知道这个子查询有多少潜在的匹配项。我可以动态设置 ROWNUM 以分块检索数据吗?

如果是,您能否举例说明 while 循环的外观,以及如何确定结果集何时耗尽? 我为此找到的一个选项是检查while @@ROWCOUNT &gt; 0 或使用:

while exists (query)

但是,我仍然不确定如何编写循环以及如何使用变量 (?) 来动态设置 ROWNUM。

基本上,我想知道我是否可以这样做:

SELECT columnA 
from tableA 
where fieldA in (
  while all results have not been fetched:
    select * 
    from
      (select a.*, rownum rnum
      from
        (select unique columnB
        from tableB
        where fieldB in 
          (select columnC
          from tableC
          where fieldC not in
            (select columnD 
            from tableD 
            where x=y 
            and a=b 
            and columnX in 
              (select columnE 
              from tableE
              where p=q)))
        and columnInTableB = <some value> 
        and anotherColumnInTableB = <some other value> 
        and thirdColumnInTableB IN (<set of values>) 
        and fourthColumnInTableB like <some string>) a
    where rownumm <= i) and rnum >= i);
    update value of i here (?) so that the loop can repeat

如何在某个循环中动态更新上面 rownum/rnum 的 'i' 的值,以检索块(例如 10000)的结果,直到结果集耗尽?

另外,while 循环应该是什么样的?

我也不知道如何使用 joins 重写它(我的 sql 知识非常有限),所以如果有人可以帮助我使用 joins 或任何其他方法更有效地重写它,那也可以。

非常感谢您对此提供的任何帮助。我已经坚持了几天了,我无法确定一个合适的解决方案。

谢谢!

【问题讨论】:

  • 如果您的问题是关于 oracle 的,为什么还要标记 mysql 和 sql-server?
  • 如果没有表、数据卷、查询及其执行计划的详细信息,我认为我们无能为力 - 它太笼统了。使用连接而不是子查询,并检查您的统计数据是否是最新的,是唯一跳出来的一般建议;我们不知道为什么你这样做的方式是个问题。也许您使用了旧语法并错过了连接条件。您似乎也在尝试遵循其他 RDBMS 的建议 - 将您的研究重点放在专门适用于 Oracle 的事物上。
  • 如果子查询是长时间运行的位,那么您可以尝试使用EXISTS 而不是IN。来自Oracle 10.2 SQL Tuning documentation“如果选择性谓词在子查询中,则使用IN。如果选择性谓词在父查询中,则使用 E​​XISTS。”
  • 我对其进行了编辑以添加有关表和一般查询结构的更多详细信息。希望这会有所帮助。
  • 你能发一份计划吗? set linesize 180 set autotrace traceonly

标签: oracle select subquery sqlplus rownum


【解决方案1】:

1) 尝试删除 UNIQUE /DISTINCT 子句。它应该在内存中排序和临时段。

2) 尝试应用 'rownum

SELECT columnA
FROM tableA
WHERE fieldA IN (
  (SELECT **UNIQUE** columnB
  FROM tableB
  WHERE fieldB IN
    (SELECT columnC
    FROM tableC
    WHERE fieldC NOT IN
      (SELECT columnD
      FROM tableD
      WHERE x      =y
      AND a        =b
      AND columnX IN
        (SELECT columnE FROM tableE WHERE p=q
        )
      )
    )
  AND columnInTableB            = <SOME value>
  AND anotherColumnInTableB     = <SOME other value>
  AND thirdColumnInTableB      IN (<
    SET OF VALUES               >)
  AND fourthColumnInTableB LIKE <SOME string>
  )
  **ROWNUM < 50** ; 

【讨论】:

    猜你喜欢
    • 2020-02-27
    • 1970-01-01
    • 1970-01-01
    • 2018-03-02
    • 2017-06-24
    • 1970-01-01
    • 1970-01-01
    • 2019-06-11
    • 2011-09-26
    相关资源
    最近更新 更多