在PL/SQL中使用绑定变量和动态SELECT INTO子句

BYS*_*YS2 42 sql oracle plsql oracle11g execute-immediate

我有一个关于绑定变量可以在PL/SQL中的动态SQL语句中使用的问题.

例如,我知道这是有效的:

CREATE OR REPLACE FUNCTION get_num_of_employees (p_loc VARCHAR2, p_job VARCHAR2) 
RETURN NUMBER
IS
  v_query_str VARCHAR2(1000);
  v_num_of_employees NUMBER;
BEGIN
  v_query_str := 'SELECT COUNT(*) FROM emp_' 
                 || p_loc
                 || ' WHERE job = :bind_job';                           
  EXECUTE IMMEDIATE v_query_str
    INTO v_num_of_employees
    USING p_job;
  RETURN v_num_of_employees;
END;
/
Run Code Online (Sandbox Code Playgroud)

我想知道你是否可以在这样的select语句中使用绑定变量

CREATE OR REPLACE FUNCTION get_num_of_employees (p_loc VARCHAR2, p_job VARCHAR2) 
RETURN NUMBER
IS
  v_query_str VARCHAR2(1000);
  v_num_of_employees NUMBER;
BEGIN
  v_query_str := 'SELECT COUNT(*) INTO :into_bind FROM emp_' 
                 || p_loc
                 || ' WHERE job = :bind_job';                           
  EXECUTE IMMEDIATE v_query_str
    USING out v_num_of_employees, p_job;
  RETURN v_num_of_employees;
END;
/
Run Code Online (Sandbox Code Playgroud)

注意我使用SELECT INTO语句作为我的dyamic字符串,并在INTO子句中使用了绑定变量.

我现在正在旅行,几天后无法在家里使用我的电脑,但这一直在唠叨我.试过阅读PL/SQL参考,但他们没有像这样的选择的例子.

谢谢

use*_*735 27

不,你不能这样使用绑定变量.在你的第二个例子:into_bind中,v_query_str它只是一个变量值的占位符v_num_of_employees.您的select into语句将变成以下内容:

SELECT COUNT(*) INTO  FROM emp_...
Run Code Online (Sandbox Code Playgroud)

因为价值v_num_of_employeesnullEXECUTE IMMEDIATE.

您的第一个示例提供了将返回值绑定到变量的正确方法.

编辑

原始海报编辑了第二个代码块,我在回答中使用OUT参数模式v_num_of_employees而不是默认IN模式.这种修改使得两个示例在功能上等同.

  • @ BYS2:是的,您可以使用`OUT`参数模式.但是为了清晰起见,我更喜欢'EXECUTE IMMEDIATE INTO`. (2认同)

Ait*_*tor 27

在我看来,动态PL/SQL块有点模糊.虽然非常灵活,但也很难调整,难以调试,很难弄清楚是什么.我的投票是你的第一个选择,

EXECUTE IMMEDIATE v_query_str INTO v_num_of_employees USING p_job;
Run Code Online (Sandbox Code Playgroud)

两者都使用绑定变量,但首先,对我来说,它比@jonearles选项更具可重复性和可调性.

  • @ BYS2:我也最喜欢这种语法.不知道性能. (2认同)

Jon*_*ler 19

将select语句放在动态PL/SQL块中.

CREATE OR REPLACE FUNCTION get_num_of_employees (p_loc VARCHAR2, p_job VARCHAR2) 
RETURN NUMBER
IS
  v_query_str VARCHAR2(1000);
  v_num_of_employees NUMBER;
BEGIN
  v_query_str := 'begin SELECT COUNT(*) INTO :into_bind FROM emp_' 
                 || p_loc
                 || ' WHERE job = :bind_job; end;';
  EXECUTE IMMEDIATE v_query_str
    USING out v_num_of_employees, p_job;
  RETURN v_num_of_employees;
END;
/
Run Code Online (Sandbox Code Playgroud)