PlSql Перевести функцию вопрос - PullRequest
3 голосов
/ 14 июля 2011

Я создал курсор, чтобы выбрать фактические данные и перебрать их, выводя необработанное значение и значение после того, как оно было преобразовано в число.Приложение иногда выдает неверные номера ошибок.Ниже мой тестовый (не включая оператор 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». </p>

Обратите внимание, что фактический код, используемый приложением, выглядит следующим образом:

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

и является частью предложения where в динамической строке sql.Я заменил оператор декодирования оператором 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;

1 Ответ

5 голосов
/ 14 июля 2011

Во-первых, ПЕРЕВОД не заменяет символ «<», потому что у него нет шанса. Оператор CASE оценивает число в одном условии и символ в другом. Если вывод вашего CASE непротиворечив, я считаю, что ваши ошибки исчезнут: </p>

  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 выдает другой исключение для этой ошибки).

EDIT:

Ваше использование 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;
...