我的PLSQL动态代码有什么问题?

时间:2016-11-24 15:13:40

标签: sql plsql oracle11g dynamic-sql

我正在学习PLSQL 3或4个月,现在我正在练习动态SQL,我编写了一个简单的程序,用Dynamic SQL更新员工的姓氏。我不知道是什么问题,因为当我调用该过程并插入参数时,我收到错误。

CREATE OR REPLACE PROCEDURE upd_emp_dyn(
  p_tname VARCHAR2,
  p_lname employees.last_name%TYPE,
  p_empid employees.employee_id%TYPE)
  IS
    v_dyn_stmt VARCHAR2(200) := 'UPDATE ' || p_tname ||
                                ' SET last_name = ' ||
                                p_lname || ' WHERE employee_id = ' ||
                                p_empid;
    v_confirm_stmt VARCHAR2(200) := 'SELECT * FROM ' || p_tname ||
                                    ' WHERE employee_id = ' ||
                                    p_empid;
BEGIN
  EXECUTE IMMEDIATE v_dyn_stmt;
  DBMS_OUTPUT.PUT_LINE(v_confirm_stmt);
END upd_emp_dyn;
/
SHOW ERRORS;

SET SERVEROUTPUT ON
BEGIN
  upd_emp_dyn('employees', 'Rooney', 120);
END;
/
Error que empieza en la línea: 2 del comando :
BEGIN
  upd_emp_dyn('employees', 'Rooney', 120);
END;
Informe de error -
ORA-00904: "ROONEY": invalid identifier
ORA-06512: at "HR.UPD_EMP_DYN", line 14
ORA-06512: at line 2
00904. 00000 -  "%s: invalid identifier"
*Cause:    
*Action:

2 个答案:

答案 0 :(得分:0)

而不是将表名作为单独的变量声明为过程中的参数。您可以为employees表&编写一个游标。在动态查询中调用该游标以打印输出。所以你的proc中的动态sql会更简单。

答案 1 :(得分:0)

最佳实践(性能和安全性)是使用参数:

CREATE OR REPLACE PROCEDURE upd_emp_dyn(
  p_tname VARCHAR2,
  p_lname employees.last_name%TYPE,
  p_empid employees.employee_id%TYPE)
  IS
    v_dyn_stmt VARCHAR2(200) := 'UPDATE ' || p_tname ||
                                ' SET last_name = :1 WHERE employee_id = :2';
    v_confirm_stmt VARCHAR2(200) := 'SELECT * FROM ' || p_tname ||
                                    ' WHERE employee_id = :1';
BEGIN
  EXECUTE IMMEDIATE v_dyn_stmt using p_lname, p_empid;
  DBMS_OUTPUT.PUT_LINE(v_confirm_stmt);
END upd_emp_dyn;
/
SHOW ERRORS;

SET SERVEROUTPUT ON
BEGIN
  upd_emp_dyn('employees', 'Rooney', 120);
END;
/

对于select语句,请使用以下内容:

declare
  result my_table%rowtype;
  id number := 123;
begin
  execute immediate 'select * from my_table where id = :1' into result using id;
end;
/

此外,它可以帮助您避免拼写错误(如导致此问题)。当然,如果可以使用静态,则应避免使用动态SQL。