Plsql 解析PL/SQL语句中用于立即执行的占位符
我只是从几天开始学习这种语言。 我试图使用一个包含PL/SQL块的字符串和一个占位符字符串,占位符字符串有两个字段,我想用从SELECT语句检索到的一些数据替换它们 我已正确创建并填充了表Plsql 解析PL/SQL语句中用于立即执行的占位符,plsql,execute-immediate,Plsql,Execute Immediate,我只是从几天开始学习这种语言。 我试图使用一个包含PL/SQL块的字符串和一个占位符字符串,占位符字符串有两个字段,我想用从SELECT语句检索到的一些数据替换它们 我已正确创建并填充了表employees 问题是我需要“替换”那些占位符(:name和:salary在变量cmd2中),但是当我使用检索到的值执行IMMEDIATE时,我会得到以下错误:ORA-01006:bind变量不存在 这是代码片段: DECLARE cmd1 VARCHAR2(200) := 'SELECT * FR
employees
问题是我需要“替换”那些占位符(:name
和:salary
在变量cmd2
中),但是当我使用检索到的值执行IMMEDIATE
时,我会得到以下错误:ORA-01006:bind变量不存在
这是代码片段:
DECLARE
cmd1 VARCHAR2(200) := 'SELECT * FROM employees';
cmd2 VARCHAR2(200) := 'BEGIN DBMS_OUTPUT.PUT_LINE('':name has a salary of :salary;''); END;';
str VARCHAR2(200);
c1 SYS_REFCURSOR;
emp employees%ROWTYPE;
BEGIN
OPEN c1 FOR cmd1;
LOOP
FETCH c1 INTO emp;
EXIT WHEN c1%NOTFOUND;
-- It doesn't work
EXECUTE IMMEDIATE cmd2 USING emp.name, emp.salary;
-- It works, but just prints ':name has a salary of :salary;'
EXECUTE IMMEDIATE cmd2;
END LOOP;
END;
预期结果应该是:
Name1 has a salary of 300;
Name2 has a salary of 700;
-- ...and so on
问题在于定义cmd2的PL/SQL:
cmd2 VARCHAR2(200) :=
'BEGIN DBMS_OUTPUT.PUT_LINE('':name has a salary of :salary;''); END;';
不能在字符串值中引用变量名-它们只是文本。这一变化将使它发挥作用
cmd2 VARCHAR2(200) :=
'BEGIN DBMS_OUTPUT.PUT_LINE(:name||'' has a salary of ''||:salary); END;';
现在,第一次执行将成功,但第二次执行将失败:
ORA-01008: not all variables bound
所以移除第二次执行,一切都会好起来
注
您的示例不是动态PL/SQL的典型用例,因为静态PL/SQL也可以实现这一点:
BEGIN
FOR r IN SELECT * FROM employees
LOOP
DBMS_OUTPUT.PUT_LINE(r.name || ' has a salary of ' || r.salary');
END LOOP;
END;
动态SQL和PL/SQL只应在不可能使用静态SQL的情况下使用,例如,因为表名、列名或过程名不是固定的。请参阅一些示例。问题在于您的PL/SQL定义cmd2:
cmd2 VARCHAR2(200) :=
'BEGIN DBMS_OUTPUT.PUT_LINE('':name has a salary of :salary;''); END;';
不能在字符串值中引用变量名-它们只是文本。这一变化将使它发挥作用
cmd2 VARCHAR2(200) :=
'BEGIN DBMS_OUTPUT.PUT_LINE(:name||'' has a salary of ''||:salary); END;';
现在,第一次执行将成功,但第二次执行将失败:
ORA-01008: not all variables bound
所以移除第二次执行,一切都会好起来
注
您的示例不是动态PL/SQL的典型用例,因为静态PL/SQL也可以实现这一点:
BEGIN
FOR r IN SELECT * FROM employees
LOOP
DBMS_OUTPUT.PUT_LINE(r.name || ' has a salary of ' || r.salary');
END LOOP;
END;
动态SQL和PL/SQL只应在不可能使用静态SQL的情况下使用,例如,因为表名、列名或过程名不是固定的。参见一些示例。绑定变量最好在
PLSQL
块中的SQL
语句中使用。您不应该在DBMS\u输出
语句中绑定变量
就你而言
cmd2 VARCHAR2(200):=“开始DBMS\u输出。放置\u行(“”:名称有薪水
其中:工资;'';"完";
这里应用BIND
变量是不正确的。这是不允许的
下面是一个使用bind变量的简单示例
SQL> DECLARE
2 cmd1 VARCHAR2(200) := 'SELECT * FROM EMP';
3 cmd2 VARCHAR2(200) := 'SELECT * FROM EMP WHERE ENAME = :name and sal =:salary'; --<--See how bind variables are used
4 str VARCHAR2(200);
5
6 c1 SYS_REFCURSOR;
7
8 emp1 emp%ROWTYPE;
9 BEGIN
10 OPEN c1 FOR cmd1;
11 LOOP
12 FETCH c1 INTO emp1;
13 EXIT WHEN c1%NOTFOUND;
14
15 -- It doesn't work
16 EXECUTE IMMEDIATE cmd2 USING emp1.ename, emp1.sal;
17
18
19 END LOOP;
20 END;
21 /
PL/SQL procedure successfully completed.
SQL>
SQL>DECLARE
2 cmd1 VARCHAR2(200):=“从EMP中选择*”;
3 cmd2 VARCHAR2(200):=“从EMP中选择*,其中ENAME=:name,sal=:salary”-- 绑定变量最好用在PLSQL
块中的SQL
语句中。您不应该在DBMS\u输出
语句中绑定变量
就你而言
cmd2 VARCHAR2(200):=“开始DBMS\u输出。放置\u行(“”:名称有薪水
其中:工资;'';"完";
这里应用BIND
变量是不正确的。这是不允许的
下面是一个使用bind变量的简单示例
SQL> DECLARE
2 cmd1 VARCHAR2(200) := 'SELECT * FROM EMP';
3 cmd2 VARCHAR2(200) := 'SELECT * FROM EMP WHERE ENAME = :name and sal =:salary'; --<--See how bind variables are used
4 str VARCHAR2(200);
5
6 c1 SYS_REFCURSOR;
7
8 emp1 emp%ROWTYPE;
9 BEGIN
10 OPEN c1 FOR cmd1;
11 LOOP
12 FETCH c1 INTO emp1;
13 EXIT WHEN c1%NOTFOUND;
14
15 -- It doesn't work
16 EXECUTE IMMEDIATE cmd2 USING emp1.ename, emp1.sal;
17
18
19 END LOOP;
20 END;
21 /
PL/SQL procedure successfully completed.
SQL>
SQL>DECLARE
2 cmd1 VARCHAR2(200):=“从EMP中选择*”;
3 cmd2 VARCHAR2(200):=“从EMP中选择*,其中ENAME=:name,sal=:salary”-- 绑定变量位于字符串中,因此它们不被视为绑定
试一试
绑定变量位于字符串中,因此它们不被视为绑定
试一试
你在发布之前试过了吗。在你的案子里有效吗。这将抛出错误,我确实尝试过,但在这里键入时出现了拼写错误-应该是q'[在发布之前您是否尝试过。它在您的案例中是否有效。这将抛出错误,我尝试过,但在这里键入时出现了拼写错误-应该是q'[解决方案@ishandoq'[开始DBMS_输出。PUT_行(:name | |有一个“| |:salary”);结束;]“;
效果很好!@RinoDrummer我知道在他的更正后应该可以,但这不是绑定变量的正确应用。谢谢。我将避免像这样使用it案例!我正要这样做!我投了反对票,因为你的回答说“不要这样做”,而不是说明如何做(以符合OP的要求)。没有规则规定,只要语法正确,就不能或不应该将变量绑定到动态PL/SQL块中的DBMS_输出语句中!在现实生活中是否真的要绑定是另一回事…”绑定变量仅在PLSQL块中的SQL语句中使用不正确。它们可能是最好的或通常仅在SQL语句中使用,但没有限制。@ishandoq'[BEGIN DBMS|u OUTPUT.PUT|u LINE(:name | |有一个“| |:salary”);END;]“;
效果很好!@RinoDrummer我知道在他的更正后应该可以,但这不是绑定变量的正确应用。谢谢。我将避免像这样使用it案例!我正要这样做!我投了反对票,因为你的回答说“不要这样做”,而不是说明如何做(以符合OP的要求)。没有规则规定,只要语法正确,就不能或不应该将变量绑定到动态PL/SQL块中的DBMS_输出语句中!在现实生活中是否真的要绑定是另一回事…”绑定变量仅在PLSQL块中的SQL语句中使用不是真的。它们可能是最好的,或者通常只在SQL语句中使用,但没有限制。即使您接受了最不适合您的问题的答案,我想再说一次,绑定变量应用程序只是不适用于DBMS\u输出
语句。@XING在您的答案中添加了一个引号。q的重要性如果您接受了某种程度上解决了您的问题但作为概念点可能会产生误导的任何答案,那么问题就会减少。如果您添加了任何引号,这并不重要,因为这样的人看的是答案,而不是问题“绑定变量仅用于PLSQL块中的SQL语句。”但这是错误的,它们也用于过程调用中传递参数-参见许多示例。和DBMS\u OUTPUT.PUT\u LINE