执行立即错误:PL/SQL:数字或值错误:字符到数字转换错误

Posted

技术标签:

【中文标题】执行立即错误:PL/SQL:数字或值错误:字符到数字转换错误【英文标题】:Execute Immediate Error: PL/SQL: numeric or value error: character to number conversion error 【发布时间】:2018-07-11 06:24:44 【问题描述】:

我有以下代码,我试图动态传递 IF 语句条件:

DECLARE
v_flag            NUMBER(2);
v_if_statement VARCHAR2(500);
v_sql_statement VARCHAR2(500);
v_criteria        VARCHAR2(150);
v_condition VARCHAR2(30) := '%sales% > 300';
BEGIN
v_criteria := REPLACE(v_condition , '%sales%' , 500.32);

      v_if_statement := 'IF :'||v_criteria||' '||
          'THEN :v_flag := 1;'||' '||
      'ELSE :v_flag := 0;'||' '||
          'END IF;';

v_sql_statement := 'BEGIN '||v_if_statement||' END;';         


      EXECUTE IMMEDIATE v_sql_statement USING IN v_criteria, OUT v_flag;
       dbms_output.put_line('The output is : '||v_flag);

 END;

我收到以下错误: ORA-06502: PL/SQL: 数字或值错误: 字符到数字的转换错误

任何帮助将不胜感激!

谢谢..

【问题讨论】:

在构建变量v_sql_statement之后,在执行它之前,把它打印出来看看全貌——然后你就可以很容易地发现问题了。 【参考方案1】:

如果您按照@Ychdziu 的建议打印出最终生成的语句,您会看到它最终为:

BEGIN IF :500.32 > 300 THEN :v_flag := 1; ELSE :v_flag := 0; END IF; END;

这不是你想要的。您要么需要提供要检查的值 (500.32) 作为绑定变量,如@Ychdziu 的回答中所示,要么将条件连接到语句中而不尝试创建另一个绑定变量:

DECLARE
  v_flag          NUMBER(2);
  v_if_statement  VARCHAR2(500);
  v_sql_statement VARCHAR2(500);
  v_criteria      VARCHAR2(150);
  v_condition     VARCHAR2(30) := '%sales% > 300';
BEGIN
  v_criteria := REPLACE(v_condition , '%sales%' , 500.32);

  v_if_statement := 'IF '||v_criteria||' '||
    'THEN :v_flag := 1;'||' '||
    'ELSE :v_flag := 0;'||' '||
    'END IF;';

  v_sql_statement := 'BEGIN '||v_if_statement||' END;';         
  dbms_output.put_line('statament: '||v_sql_statement);

  EXECUTE IMMEDIATE v_sql_statement USING OUT v_flag;
  dbms_output.put_line('The output is : '||v_flag);

 END;
/

现在生成的语句是

BEGIN IF 500.32 > 300 THEN :v_flag := 1; ELSE :v_flag := 0; END IF; END;

所以只有一个绑定变量。

但如果可以的话,通常最好绑定变量。在您的示例代码中,整个条件似乎是一个变量(我假设这只是一个练习,但它可以传入或来自表),因此您可以将两者结合起来并用绑定变量替换 %sales% 占位符改为参考:

DECLARE
  v_flag          NUMBER(2);
  v_if_statement  VARCHAR2(500);
  v_sql_statement VARCHAR2(500);
  v_criteria      VARCHAR2(150);
  v_condition     VARCHAR2(30) := '%sales% > 300';
BEGIN
  v_criteria := REPLACE(v_condition , '%sales%' , ':v_value');

  v_if_statement := 'IF '||v_criteria||' '||
    'THEN :v_flag := 1;'||' '||
    'ELSE :v_flag := 0;'||' '||
    'END IF;';

  v_sql_statement := 'BEGIN '||v_if_statement||' END;';         
  dbms_output.put_line('statament: '||v_sql_statement);

  EXECUTE IMMEDIATE v_sql_statement USING IN 500.32, OUT v_flag;
  dbms_output.put_line('The output is : '||v_flag);

 END;
/

不是生成的语句是:

BEGIN IF :v_value > 300 THEN :v_flag := 1; ELSE :v_flag := 0; END IF; END;

您可以通过USING 子句直接传递您想要检查的实际值500.32 - 可以像我在这里所做的那样作为文字,或者使用单独的数字变量。

【讨论】:

【参考方案2】:

这个查询有几个问题: 1)SQL语句本身结构不好; 2) DB 尝试将 v_criteria 转换为数字类型,但 v_criteria 是 '500.32 > 300' - 你不能这样转换。 试试这个方法:

DECLARE
  v_flag            NUMBER(2);
  v_if_statement VARCHAR2(500);
  v_sql_statement VARCHAR2(500);
  v_criteria        VARCHAR2(150);
BEGIN
  v_criteria := 300.32;

  v_if_statement := q'[IF :v_criteria > 300
      THEN :v_flag := 1;
  ELSE :v_flag := 0;
      END IF;]';

  v_sql_statement := 'BEGIN '||v_if_statement||' END;';         
  dbms_output.put_line('v_sql_statement is : '||v_sql_statement);


  EXECUTE IMMEDIATE v_sql_statement USING IN v_criteria, OUT v_flag;
  dbms_output.put_line('The output is : '||v_flag);

END; 

【讨论】:

以上是关于执行立即错误:PL/SQL:数字或值错误:字符到数字转换错误的主要内容,如果未能解决你的问题,请参考以下文章

获取 ORA-06502:PL/SQL:数字或值错误:SQL 触发器中的字符到数字转换错误

ORA-06502 PL/SQL:数字或值错误:字符到数字的转换错误;

ORA-06502: PL/SQL: 数字或值错误: 字符到数字的转换错误

Oracle ORA-06502 PL/SQL:数字或值错误:字符到数字的转换错误

错误 ORA-06502:PL/SQL:数字或值错误:字符到数字的转换错误 ORA-06512:在第 22 行

收到错误“ORA-06502:PL/SQL:数字或值错误:字符串缓冲区太小”