2011-07-14 72 views
3

我创建了一个游标来选择实际数据,并循环输出原始值和转换为数字后的值。应用程序偶尔会抛出无效的数字错误。以下是我的测试(不包括select语句)代码和输出。PlSql转换功能问题

LOOP 
    FETCH myCursor into v_answer; 
    EXIT WHEN myCursor%notfound; 

    DBMS_OUTPUT.PUT_LINE('Raw answer: ' || v_answer); 

    v_instr := INSTR(v_answer, '.',1 , 2) ; 
    v_number := TO_NUMBER(REPLACE(TRANSLATE (CASE v_instr 
              WHEN 0 THEN UPPER(v_answer) 
              ELSE 0 
              END,'ABCDEFGHIJKLMNOPQURSTWVXYZ+<>:',' '), ' ','')); 

    DBMS_output.put_line('As number: ' || v_number); 

这里是输出:

Raw answer: 4 
As number: 4 
Raw answer: 3 
As number: 3 
Raw answer: 1.00 
As number: 1 
Raw answer: <3 

我收到:

PL/SQL: numeric or value error: character to number conversion error

...当原料答案是 '< 3'。

请注意,应用程序使用的实际代码看起来像这样:

AND TO_NUMBER(REPLACE(TRANSLATE (decode(INSTR(hra_ans.answer_text, '.',1 , 2), 0 , UPPER(hra_ans.answer_text) , 0),'ABCDEFGHIJKLMNOPQURSTWVXYZ+<>:',' '), ' ','')) 

,是一个动态的SQL字符串where子句的一部分。我用case语句替换了decode语句,因为我得到的是一个函数或伪列'DECODE'可能在SQL语句唯一错误中使用。

最后,我的问题是:

  1. 为什么没有翻译功能替换小于号和
  2. 是什么ORA-1722和ORA-之间的差异(通俗地说) 06502错误?

编辑:我注意到,当我改变的情况下声明:

CASE v_instr 
               WHEN 0 THEN UPPER(v_answer) 
               ELSE '0' 

我不再收到06502错误。从查看我发布的原始代码行,是否有什么可能会导致无效数字错误的建议(假设没有字符存在于要翻译的字符串中没有考虑到)?或者,有没有更好的方法来完成原始开发人员试图做的事情?

下面是变量声明:

v_answer varchar2(2000); 
v_number number; 
v_instr number; 
+0

相关错误的标记信息可能会提供一些关于#2的信息。我希望根据我读的ORA-06502 –

+0

来查看变量声明。请参阅我的编辑。我会检查标签。谢谢! –

回答

5

首先,翻译是不更换“<”符号,因为它没有得到机会。 CASE声明正在评估一个条件中的数字和另一个条件中的字符。如果你的情况的输出是一致的,我相信你的错误消失:

v_number := TO_NUMBER(REPLACE(TRANSLATE (CASE TO_CHAR(v_instr) 
              WHEN '0' THEN UPPER(v_answer) 
              ELSE '0' 
              END,'ABCDEFGHIJKLMNOPQURSTWVXYZ+<>:',' '), ' ','')); 

this post on asktom.com

ORA-1722 is Invalid number. We've attempted to either explicity or implicitly convert a character string to a number and it is failing.

This can happen for a number of reasons. It generally happens in SQL only (during a query) not in plsql (plsql throws a different exception for this error).

编辑:

您使用REGEXP_REPLACE的看起来不错,但如果我是编码这我会使用CASE而不是DECODE仅仅因为我认为它更容易阅读:

v_number := CASE WHEN INSTR(v_answer, '.',1 , 2) = 0 THEN -- has 0 or 1 period 
        TO_NUMER(REGEXP_REPLACE(v_answer,'[^0-9.]','')) 
       ELSE 0 -- has more than one period 
      END; 
+0

你能告诉我是否有更好的方法来完成这个工作:TO_NUMBER(REPLACE(TRANSLATE(decode(INSTR(hra_ans.answer_text,'。',1,2),0,UPPER(hra_ans.answer_text),0)), 'ABCDEFGHIJKLMNOPQURSTWVXYZ + <>:',''),'',''))?我在考虑删除翻译并使用to_number(TRIM(Regexp_replace(decode(INSTR(hra_ans.answer_text,'。',1,2),0,UPPER(hra_ans.answer_text),0),'[^ 0- 9.]',''))。任何想法? –

+0

请参阅我编辑的答案。 – DCookie