暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 查询使用大列表,结果完全错误

askTom 2017-07-23
300

问题描述

亲爱的汤姆,
我有一个表,测试 (ID,DeleteFlg) 有大约100万条记录。我需要做的就是更新给定idList(100.000元素) 的DeleteFlg。
我试图做的是:
更新测试
设置DeleteFlg = true
其中 (ID IN(1,2 ..1000) 或ID IN(1001 ...2000) 或... 或ID IN(99001,..99999))
=> 结果: 仅34463记录更新

或者我试过了
SELECT count(1) FROM TEST 其中 (ID IN(1,2 ..1000) 或ID IN(1001 ...2000) 或... 或ID IN(99001,..99999))
=> 结果只返回34463

你能解释一下为什么会发生这种情况,以及什么是解决方案。

高级感谢,
约翰

专家解答

哇 .... 请告诉我,这只是一个练习,而不是以任何方式打算作为你的应用程序的任何真正的解决方案...

我们对列表中的1000项目有限制是有原因的。因为除此之外,这意味着它不是您应该进行SQL编码的方式。解析开销变得巨大,SQL变得非常长。

这只是一个糟糕的坏主意-您将开始遇到各种各样的边界情况。

例如

SQL> create table t as
  2  select rownum x from dual
  3  connect by level <= 200000;

Table created.

SQL>
SQL> set serverout on
SQL> declare
  2    l_sql clob;
  3    l_parm varchar2(32767);
  4  b例如in
  5    dbms_lob.createtemporary(l_sql,true);
  6    l_sql := 'delete from t';
  7
  8    l_parm := ' where x in (';
  9    for i in 1 .. 1000 loop
 10      l_parm := l_parm || i ||',';
 11    end loop;
 12    l_parm := rtrim(l_parm,',')||')';
 13    dbms_lob.writeappend(l_sql,length(l_parm),l_parm);
 14
 15    for j in 1 .. 10 loop
 16      l_parm := ' or x in (';
 17      for i in j*1000+1 .. (j+1)*1000 loop
 18        l_parm := l_parm || i ||',';
 19      end loop;
 20      l_parm := rtrim(l_parm,',')||')';
 21      dbms_lob.writeappend(l_sql,length(l_parm),l_parm);
 22    end loop;
 23
 24    dbms_output.put_line('SQL length = '||dbms_lob.getlength(l_sql));
 25
 26    execute immediate l_sql;
 27    dbms_output.put_line(sql%rowcount);
 28  end;
 29  /
SQL length = 55020
11000

PL/SQL procedure successfully completed.

SQL>
SQL>
SQL>
SQL>   set serverout on
SQL> declare
  2    l_sql clob;
  3    l_parm varchar2(32767);
  4  b例如in
  5    dbms_lob.createtemporary(l_sql,true);
  6    l_sql := 'delete from t';
  7
  8    l_parm := ' where x in (';
  9    for i in 1 .. 1000 loop
 10      l_parm := l_parm || i ||',';
 11    end loop;
 12    l_parm := rtrim(l_parm,',')||')';
 13    dbms_lob.writeappend(l_sql,length(l_parm),l_parm);
 14
 15    for j in 1 .. 20 loop   -- doubled the number of iterations
 16      l_parm := ' or x in (';
 17      for i in j*1000+1 .. (j+1)*1000 loop
 18        l_parm := l_parm || i ||',';
 19      end loop;
 20      l_parm := rtrim(l_parm,',')||')';
 21      dbms_lob.writeappend(l_sql,length(l_parm),l_parm);
 22    end loop;
 23
 24    dbms_output.put_line('SQL length = '||dbms_lob.getlength(l_sql));
 25
 26    execute immediate l_sql;
 27    dbms_output.put_line(sql%rowcount);
 28  end;
 29  /
ERROR:
ORA-03114: not connected to ORACLE


declare
*
ERROR at line 1:
ORA-03113: end-of-file on communication channel
Process ID: 10840
Session ID: 267 Serial number: 48091
复制


如果您有100,000项要删除-将它们放入表中,然后执行以下操作:

从T中删除
where item in (从item_table中选择id);

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论