ORA-01722: недопустимый номер в инструкции Case

#oracle #stored-procedures #oracle11g #group-by

#Oracle #хранимые процедуры #oracle11g #группировка по

Вопрос:

Привет, я новичок в базе данных oracle.В приведенном ниже запросе ZERO_BAL_CODE varchar2 указан тип данных. Я попытался написать оператор case, но он выдает ошибку с указанием этого "ORA-01722: invalid number" . Помогите мне решить эту проблему. Заранее спасибо.

   SELECT id_loan,
         MAX (TO_NUMBER (delinq_status)) AS delinq_status,
         MAX (loan_age) AS loan_age,
         MAX (zero_bal_code) AS zero_bal_code,
         MAX (vintage) AS vintage,
         MIN (actual_loss) AS actual_loss,
         MIN (NULLIF (current_upb, 0)) AS current_upb,
         loan_type
    FROM (SELECT master_copy.id_loan,
                 loan_age,
                 master_copy.vintage,
                 delinq_status,
                 zero_bal_code,
                 master_copy.actual_loss,
                 current_upb,
                 CASE
                    WHEN (zero_bal_code IN (3)) THEN 'default_foreclosure'
                    WHEN (zero_bal_code IN (1)) THEN 'prepaid'
                    WHEN (zero_bal_code IN (6)) THEN 'default_reo'
                    WHEN (zero_bal_code IN (9)) THEN 'active'
                 END
                    AS loan_type
            FROM master_copy
                 INNER JOIN (SELECT id_loan FROM master_copy) a
                    ON master_copy.id_loan = a.id_loan) b
GROUP BY id_loan, loan_type;
 

Комментарии:

1. Попробуйте добавить кавычки и проверить пример:(‘1’)

2. Итак, общий ответ таков: это то, что происходит, когда у нас есть модель данных, которая хранит числовые значения в строковых столбцах. Независимо от того, насколько пуленепробиваемой мы можем считать проверку приложения, уроки истории заключаются в том, что наши данные неизбежно будут повреждены.

3. @Raghavi — это почти всегда проблема с данными . Есть некоторые записи, которые имеют нечисловые значения в столбцах, где вы ожидаете, что они будут иметь только числовые значения. Если вы оспариваете это, пожалуйста, опубликуйте структуру таблицы и некоторые примеры записей, которые создают эту проблему.

Ответ №1:

Вы не опубликовали описание таблицы, поэтому — для меня — это выглядит подозрительно:

 MAX (TO_NUMBER (delinq_status)) AS delinq_status,
 

Если DELINQ_STATUS бы тип данных столбца был NUMBER , вам бы это не TO_NUMBER понадобилось. Если это так VARCHAR2 , то кто-то, возможно, ввел в него ‘ABC1234’, что привело бы TO_NUMBER к сбою функции.

Итак, если вы запустите это, каков результат?

 select max(to_number(delinq_status)) from master_copy
 

По состоянию на отсутствие одинарных кавычек в CASE : id зависит от содержимого столбца. Если это «число», одинарные кавычки не нужны, хотя тип данных столбца есть VARCHAR2 (но это было бы хорошей практикой; с другой стороны, если столбец содержит только числа, почему не его тип NUMBER данных ?):

 SQL> create table test (zero_bal_code varchar2(1));

Table created.

SQL> insert into test values ('1');

1 row created.

SQL> select case when zero_bal_code in (3) then 'default_foreclosure'
  2              else 'unknown'
  3         end loan_type
  4  from test;

LOAN_TYPE
-------------------
unknown
 

Однако, если есть что-то отличное от «чисел», тогда имеют значение одинарные кавычки:

 SQL> insert into test values ('B');

1 row created.

SQL> select case when zero_bal_code in (3) then 'default_foreclosure'
  2              else 'unknown'
  3         end loan_type
  4  from test;
ERROR:
ORA-01722: invalid number



no rows selected

SQL> select case when zero_bal_code in ('3') then 'default_foreclosure'
  2              else 'unknown'
  3         end loan_type
  4  from test;

LOAN_TYPE
-------------------
unknown
unknown

SQL>
 

Кстати, то, что вы написали, не имеет особого смысла; действительно ли коды для prepault_reo, default_reo и active 1 ? Все они? Как вы будете различать, что есть что?

              CASE
                WHEN (zero_bal_code IN (3)) THEN 'default_foreclosure'
                WHEN (zero_bal_code IN (1)) THEN 'prepaid'
                WHEN (zero_bal_code IN (1)) THEN 'default_reo'
                WHEN (zero_bal_code IN (1)) THEN 'active'
             END
 

Комментарии:

1. Извините.. значение default_reo равно 6, а значение active равно 9. выбор max(to_number(delinq_status)) из master_copy возвращает недопустимое число.

2. Это означает, что сначала вы должны исправить значения столбцов DELINQ_STATUS. Он не должен содержать ничего, кроме чисел (если вы хотите применить к нему TO_NUMBER).

3. ВЫБЕРИТЕ ID_LOAN,max(to_number(DELINQ_STATUS)) как DELINQ_STATUS,max(loan_age) КАК LOAN_AGE,max(ZERO_BAL_CODE) как ZERO_BAL_CODE,max(vintage) как vintage, min(ACTUAL_LOSS) как actual_loss,MIN(NULLIF(current_upb,0)) как current_upb,’prepaid’ как loan_type ИЗ (ВЫБЕРИТЕ m.ID_LOAN,LOAN_AGE, m.vintage,DELINQ_STATUS,ZERO_BAL_CODE,m.ACTUAL_LOSS,current_upb ИЗ master_copy m INNER JOIN (ВЫБЕРИТЕ ID_LOAN ИЗ master_copy, ГДЕ ZERO_BAL_CODE В (1))A НА m.ID_LOAN= A.ID_LOAN) B группа по ID_LOAN)); но это работает нормально. здесь я пытаюсь объединить в качестве оператора case, который выдает ошибку.

4. Сколько строк вернул этот запрос? Если вы используете какой-либо графический интерфейс, они обычно возвращают пару сотен строк — не все из них. Итак, если в этом наборе данных нет ошибки, запрос будет выполнен «успешно» (скрыв ошибку). Если вы перейдете к концу строк, вы, вероятно, попадете в него. В любом случае: DELINQ_STATUS не должен содержать ничего, кроме чисел. Заключите значения ZERO_BAL_CODE в одинарные кавычки.

5. Он также пробовал использовать одинарные кавычки … все та же ошибка.

Ответ №2:

Попробуйте это с помощью ‘:

   SELECT id_loan,
         MAX (TO_NUMBER (delinq_status)) AS delinq_status,
         MAX (loan_age) AS loan_age,
         MAX (zero_bal_code) AS zero_bal_code,
         MAX (vintage) AS vintage,
         MIN (actual_loss) AS actual_loss,
         MIN (NULLIF (current_upb, 0)) AS current_upb,
         loan_type
    FROM (SELECT master_copy.id_loan,
                 loan_age,
                 master_copy.vintage,
                 delinq_status,
                 zero_bal_code,
                 master_copy.actual_loss,
                 current_upb,
                 CASE
                    WHEN (zero_bal_code IN ('3')) THEN 'default_foreclosure'
                    WHEN (zero_bal_code IN ('1')) THEN 'prepaid'
                    WHEN (zero_bal_code IN ('1')) THEN 'default_reo'
                    WHEN (zero_bal_code IN ('1')) THEN 'active'
                 END
                    AS loan_type
            FROM master_copy
                 INNER JOIN (SELECT id_loan FROM master_copy) a
                    ON master_copy.id_loan = a.id_loan) b
GROUP BY id_loan, loan_type;