概要描述
本文档基于 Inceptor错误代码与信息查询手册 10.23 小节的 ERROR_11073 “Number of placeholders {0} doesn’t match number of arguments {1} for dynamic sql: {2}” 错误,列出了几种常见场景和解决方法,欢迎补充关于该问题的更多场景。
详细说明
- Case 1: EXECUTE IMMEDIATE 向其后执行的SQL语句传递的参数数量,和原语句定义的匹配参数数量不一致
如下过程:
CREATE OR REPLACE PROCEDURE test_11073()
IS
DECLARE
v_sql STRING;
BEGIN
EXECUTE IMMEDIATE "DROP TABLE IF EXISTS tab_11073";
EXECUTE IMMEDIATE "CREATE TABLE tab_11073(c1 INT, c2 STRING, c3 STRING)
CLUSTERED BY(c1) INTO 1 BUCKETS STORED AS ORC_TRANSACTION";
v_sql := "INSERT INTO tab_11073 VALUES (:v_c1, :v_c2, :v_c3)";
EXECUTE IMMEDIATE v_sql USING 1,'A','B','C';
END;
/
CALL test_11073();
分析:该 case 是很明显的手册里描述的场景,在 EXECUTE IMMEDIATE 后 USING 的参数数量为 4 个,而 v_sql 语句里绑定变量参数只有 3 个,故而报参数数量不一致。
解决办法:USING 后面的参数数量和原 SQL 里绑定的参数数量保持一致,写存过时细心即可。
- Case 2: EXECUTE IMMEDIATE 后执行的 SQL语句含有带 ":" 常量
如下过程:
CREATE OR REPLACE PROCEDURE test_11073()
IS
DECLARE
v_sql STRING;
BEGIN
EXECUTE IMMEDIATE "SELECT '2019-08-19 13:00:00 a:b:c' FROM system.dual" INTO v_sql;
DBMS_OUTPUT.PUT_LINE(v_sql);
END;
/
CALL test_11073();
分析:该 case 中,EXECUTE IMMEDIATE 后的 SQL 语句里含有带 ":" 的常量,故而在执行该动态 SQL 时会把 ":" 后的值当作参数,几个 ":" 就认为有几个参数 ,所以会报 Number of placeholders 4 doesn’t match number of arguments 0.
解决办法:将 ‘2019-08-19 13:00:00 a:b:c’ 里的 ":" 用 "\:" 转义
- Case 3: EXECUTE IMMEDIATE 后执行的 SQL语句含有带 ":" 变量
如下过程:
CREATE OR REPLACE PROCEDURE test_11073()
IS
DECLARE
v_sql STRING;
v_ARG TIMESTAMP := SYSDATE;
v_ARG_CHG STRING := REPLACE(v_ARG,':','\:');
BEGIN
v_sql := "SELECT '" || v_ARG || "' FROM system.dual";
EXECUTE IMMEDIATE v_sql;
DBMS_OUTPUT.PUT_LINE(v_sql);
END;
/
CALL test_11073();
分析:该 case 中,EXECUTE IMMEDIATE 后执行的 v_sql 的 SQL 语句里带有变量 v_ARG,该变量数据类型为 TIMESTAMP,其值里带有 ":" 所以会报 Number of placeholders 2 doesn’t match number of arguments 0.
解决办法:将 v_ARG 变量里的 ":" 用 "\:" 替换,如上面 Case3 中定义的 v_ARG_CHG STRING := REPLACE(v_ARG,':','\:')
, 然后将 v_sql 里的 v_ARG 替换为 v_ARG_CHG.