这是我的plsql块,动态SQL。我找不到一个原因,为什么它会出现一个错误'no ORA-01008: not all variables bound ORA-06512: at line 23'。
我在EXECUTE IMMEDIATE语句中找不到错误。
DECLARE
form_name VARCHAR2(225) := 'MUST AS';
ad_no VARCHAR2(225) := :ad_no;
sql_stmt VARCHAR2(4000);
sql_output VARCHAR2(4000);
db_table VARCHAR(225) := inp_reminder_pkg.form_db_table(form_name);
col_id VARCHAR(225) := inp_reminder_pkg.get_col_id(form_name);
BEGIN
sql_stmt := '
SELECT :1
FROM @tableName
WHERE advno = :2
AND created = ( SELECT MAX(CREATED)
FROM @tableName
WHERE advno = :2 )'
;
sql_stmt := replace(sql_stmt, '@tableName', db_table);
EXECUTE IMMEDIATE sql_stmt
INTO sql_output
USING col_id, ad_no;
dbms_output.put_line(sql_output);
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('no-data');
END;
让我知道我错过了什么。谢谢你有三个绑定变量(即使两个具有相同的名称),您需要在execute immediate
语句中为它们发送3个参数。
请注意,您可能并不是要将列名作为绑定变量输入,如果您想要选择一个变量列,则必须动态执行此操作。
你的代码有两个问题:
- 动态查询有两个占位符
:advno
的实例,因此您需要在USING子句中传递两个值。是的,这是有点垃圾,但我猜Oracle觉得解析动态SQL足够困难,而不要求编译器匹配占位符名称。 - 我们不能传递列名或其他标识符作为参数。我们必须拆分语句以引用列名变量。出于同样的原因,您可以使用
replace()
调用来替换表名。
所以你需要改变你的程序,使它看起来像这样:
DECLARE
form_name VARCHAR2(225) := 'MUST AS';
ad_no VARCHAR2(225) := :ad_no;
sql_stmt VARCHAR2(4000);
sql_output VARCHAR2(4000);
db_table VARCHAR(225) := inp_reminder_pkg.form_db_table(form_name);
col_id VARCHAR(225) := inp_reminder_pkg.get_col_id(form_name);
BEGIN
sql_stmt := '
SELECT ' || col_id || '
FROM @tableName
WHERE advno = :2
AND created = ( SELECT MAX(CREATED)
FROM @tableName
WHERE advno = :2 )'
;
sql_stmt := replace(sql_stmt, '@tableName', db_table);
EXECUTE IMMEDIATE sql_stmt
INTO sql_output
USING ad_no, ad_no;
dbms_output.put_line(sql_output);
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('no-data');
END;