PlSql翻译函数问题

发布于 2024-11-20 00:11:30 字数 1712 浏览 4 评论 0原文

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

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:数字或值错误:字符到数字转换错误

...当原始答案为“<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”可能仅在 SQL 语句中使用的错误。

最后,我的问题是:

  1. 为什么翻译函数不替换小于号以及
  2. ORA-1722 和 ORA-06502 错误之间的区别(通俗地说)是什么?

编辑:我注意到,当我将 case 语句更改为: 时

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

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

以下是变量声明:

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

I've created a cursor to select the actual data, and loop through it outputting the raw value and the value after it was converted to a number. The application occasionally throws invalid number errors. Below is my test (not including the select statement) code and the output.

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);

Here is the output:

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

I receive:

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

...when the Raw answer is '<3'.

Please note that the actual code used by the application looks like so:

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

and is part of the where clause in a dynamic sql string. I've replaced the decode statement with the case statement because I was getting an function or pseudo-column 'DECODE' may be used inside a SQL statement only error.

Finally, my questions are these:

  1. Why isn't the translate function replacing the less than sign and
  2. What is the difference (in layman's terms) between the ORA-1722 and ORA-06502 errors?

EDIT: I've noticed that when I change the case statement to:

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

,

I no longer receive the 06502 error. From looking at the original code line I posted, are there any suggestions as to what may be causing the invalid number error (assuming that no characters exist in the string to be translated are not accounted for)? Or, is there a better way to accomplish what the original developer was attempting to do?

Here are the variable declarations:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

蓬勃野心 2024-11-27 00:11:30

首先, TRANSLATE 并没有取代 '<'符号,因为它没有机会。 CASE 语句在一个条件下计算为数字,在另一个条件下计算为字符。如果您的 CASE 的输出是一致的,我相信您的错误就会消失:

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

来自 asktom.com 上的此帖子

ORA-1722 是无效号码。我们试图明确或
将字符串隐式转换为数字但失败。

发生这种情况的原因有多种。一般发生在SQL中
仅(在查询期间)不在 plsql 中(plsql 抛出不同的
此错误的例外)。

编辑:

您对 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;

First, the TRANSLATE isn't replacing the '<' symbol because it's not getting the chance. The CASE statement is evaluating to a number in one condition and a char in the other. If the output of your CASE is consistent, I believe your errors go away:

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

From 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).

EDIT:

Your use of regexp_replace looks good, but if I were coding this I'd use CASE instead of DECODE just because I think it's easier to read:

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文