【问题标题】:Oracle dynamic PL/SQL. I cant get it to workOracle 动态 PL/SQL。我无法让它工作
【发布时间】:2012-12-12 11:04:32
【问题描述】:

这是我的代码:

CREATE OR REPLACE PROCEDURE UPDATE_USER
(
  updateColumn IN USERS.column_name%type,
  changeStr IN VARCHAR2,
  unID IN VARCHAR2
)
IS
BEGIN
  EXECUTE IMMEDIATE
    'UPDATE
      users
    SET :1 = :2
    WHERE
      uniqueID = :3'
  USING updateColumn, changeStr, unID; 
END;
/

我已经为此搜索了其他答案,据我所知这应该可行。但是我得到了错误: '错误(3,25):PLS-00302:必须声明组件'COLUMN_NAME''

谢谢。

【问题讨论】:

  • 您的USERS 表是否真的有一个名为column_name 的列?这似乎不是你想要做的。您可能需要将updateColumn 声明为user_tab_columns.colmn_name%type,或简单的varchar2。但是,您不能使用绑定变量在更新中动态设置列名。
  • @AlexPoole 这个答案就是我的目标:this question

标签: oracle dynamic plsql


【解决方案1】:

错误消息指定第 3 行,第 25 个字符,它在 updateColumn 参数的声明中指向 column_name。您似乎正在尝试将要更新的列名作为参数传递,但这意味着在编译时该列是未知的,因此它的类型是未知的。这也没有任何意义 - 如果它是 number 列,那么您会尝试将列名传递给数字参数,但这无论如何都行不通。如果您不想将其声明为简单的varchar2,则可以改用user_tab_columns.column_name%type

但是您不能使用绑定变量在更新语句中动态设置列名。它会编译,但会在执行时从以冒号开头的明显名称获得ORA-01747。您需要将其连接起来,例如:

CREATE OR REPLACE PROCEDURE UPDATE_USER
(
  updateColumn IN user_tab_columns.column_name%type,
  changeStr IN VARCHAR2,
  unID IN VARCHAR2
)
IS
BEGIN
  EXECUTE IMMEDIATE
    'UPDATE
      users
    SET ' || updateColumn || ' = :1
    WHERE
      uniqueID = :2'
  USING changeStr, unID; 
END;
/

但您需要将列名清理为avoid SQL injection。例如,APC 的 answer to the question you linked to 提到使用 DBMS_ASSERT 包。

【讨论】:

  • 感谢亚历克斯。我之前确实有过连接,但是我在运行时删除了这个错误:ORA-00971: missing SET keyworduser_tab_columns.column_name%type 似乎是一种改进,但我仍然收到运行时错误。
  • @TomStone - 你确定SET 和连接前的结束引号之间有空格吗?可能值得打印查询,因为它将实际执行以进行检查。
  • 抱歉,错误现在已经消失,我收到了ORA-01006: bind variable does not exist ORA-06512: at "THOMASSTONE.UPDATE_USER", line 9 ORA-06512: at line 1
  • @TomStone - 好吧,只是猜测,但您是否将绑定变量编号改回:1:2,并从using 子句中删除updateColumn
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-13
  • 2014-09-02
  • 1970-01-01
相关资源
最近更新 更多