假设我必须针对单个更新语句检查 100,000 个 uid - 我的代码目前会将其分解为 1000 个 uid 块:
[...] WHERE UID IN (..., '998', '999', '1000')
OR UID IN ('1001', '1002', ...)
OR (..., etc., ...)
您可以拥有最大数量的 OR 子句吗?即,在我上面的示例中,它将生成 100 个 OR 子句,每个子句包含 1000 个 IN 子句。
22.
嗯,不完全是。这就是在我的系统上将运行多少个 1000 项 IN 列表的 OR 子句,但这个数字可能对每个人都不同。没有完全涵盖此方案的数据库限制。它可能属于注释:
SQL 语句的长度限制取决于许多因素,包括数据库配置、磁盘空间和内存
当我尝试 23 时,我在 SQL*Plus 中收到此错误:
ERROR at line 1:
ORA-03113: end-of-file on communication channel
Process ID: 2452
Session ID: 135 Serial number: 165
这不是真正的错误,这只是意味着服务器崩溃并且 SQL*Plus 失去了连接。奇怪的是,当我查看警报日志时,没有错误。有跟踪文件但仍然没有 ORA 错误消息。我所看到的只有数百行这样的:
*** 2013-11-04 21:59:48.667
minact-scn master-status: grec-scn:0x0000.00821c54 gmin-scn:0x0000.0081d656 gcalc-scn:0x0000.00821c54
minact-scn master-status: grec-scn:0x0000.00823b45 gmin-scn:0x0000.0081d656 gcalc-scn:0x0000.00823b46
这里的教训是避免大得离谱的 SQL 语句。您必须以另一种方式进行,例如将数据加载到表中。并且不要试图构建足够小的东西。它今天可能工作,但明天在不同的环境中失败。
--Find the maximum number of IN conditions with 1000 items.
--Change the first number until it throws an error.
--This code uses dynamic SQL, but I found that static SQL has the same limit.
declare
c_number_of_ors number := 22;
v_in_sql varchar2(4000);
v_sql clob;
v_count number;
begin
--Comma-separate list of 1000 numbers.
select listagg(level, ',') within group (order by 1)
into v_in_sql
from dual connect by level <= 1000;
--Start the statement.
v_sql := 'select count(*) from dual ';
v_sql := v_sql || 'where 1 in ('||v_in_sql||')';
--Append more ORs to it.
for i in 1 .. c_number_of_ors loop
v_sql := v_sql || ' or '||to_char(i)||' in ('||v_in_sql||')';
end loop;
--Execute it.
execute immediate v_sql into v_count;
end;
/
单个查询中的 OR 子句没有任何限制。当您使用 GROUP BY 子句时,您可能会遇到限制问题,一般而言,所有非可区分聚合函数(例如,SUM、AVG)必须适合单个数据库块。