问题描述
亲爱的汤姆,
我有一个表,测试 (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
你能解释一下为什么会发生这种情况,以及什么是解决方案。
高级感谢,
约翰
我有一个表,测试 (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变得非常长。
这只是一个糟糕的坏主意-您将开始遇到各种各样的边界情况。
例如
如果您有100,000项要删除-将它们放入表中,然后执行以下操作:
从T中删除
where item in (从item_table中选择id);
我们对列表中的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进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。