【问题标题】:What is wrong with my PLSQL dynamic code?我的 PLSQL 动态代码有什么问题?
【发布时间】:2017-04-08 22:56:14
【问题描述】:

我从 3 或 4 个月开始学习 PLSQL,现在我正在练习动态 SQL,并且我编写了一个简单的程序来使用动态 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:

【问题讨论】:

  • 如果您在 v_dyn_stmt 中显示您的动态 SQL 语句(例如,使用 DBMS_OUTPUT.PUT_LINE 您会明白原因:set lastname = Rooney...
  • 不应该 ISAS 吗?另外,除了/ 之外的行的目的是什么?
  • 不要将字符串连接到动态 SQL 中。使用占位符和参数。在您的情况下,update 缺少围绕 p_lname 值的所需单引号
  • @DanBracuk - 同意AS 在这里比IS 读得更好,但两者都是有效的。某些工具(尤其是 SQL*Plus)需要 /(斜杠)来终止 PL/SQL 块。

标签: sql plsql oracle11g dynamic-sql


【解决方案1】:

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

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,您应该避免使用动态 SQL。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-28
      • 1970-01-01
      • 2019-06-06
      • 1970-01-01
      相关资源
      最近更新 更多