ORA-01722: недопустимый номер при выборе числового столбца и ссылка на тот же числовой столбец, где - PullRequest
0 голосов
/ 25 июня 2019
select id 
from abc 
where id =  1001;

вернуть неверный номер.

  1. abc - это вид
  2. тип данных id - это число
  3. При создании представления используется
CREATE OR REPLACE VIEW abc AS 
SELECT CAST (SUBSTR(T_ID,3,100) AS NUMBER) AS ID
from TEST
  1. Столбец id содержит только все числовые значения
  2. SELECT * FROM ABC РАБОТАЕТ ИЗБИРАТЕЛЬНО И ТАК работает запрос вставки

попробовал код ниже, который ничего не возвращает в выводе DBMS

declare
  l_dummy number;
begin
  for cur in (select ID from abc)
  loop
     begin
        l_dummy := to_number(cur.ID);

     exception
        when others then dbms_output.put_line(cur.ID);
     end;
  end loop;
end;

column  datatype nullable
ID  NUMBER  Yes     1       NO  NO  NO

SELECT *
FROM abc
WHERE 
ID = 1001

возвращает:

ORA-01722: invalid number
01722. 00000 -  "invalid number"
*Cause:    The specified number was invalid.
*Action:   Specify a valid number.

1 Ответ

0 голосов
/ 25 июня 2019

Есть две проблемы:

  1. SUBSTR (T_ID, 3,100) не всегда будет возвращать число - нам нужно рассмотреть только числовой запрос
  2. Если мы применим что-либо в WHEREусловие представления, Порядок выполнения условия WHERE - вызов оптимизатора Oracle.

Пожалуйста, смотрите ниже код:

-- Data preparation
create table TEST (T_ID varchar2(20));
INSERT INTO TEST VALUES('AB1000'); -- Good data
INSERT INTO TEST VALUES('AB1001'); -- Good data
INSERT INTO TEST VALUES('CD1001'); -- Good data
INSERT INTO TEST VALUES('XY1004'); -- Good data
INSERT INTO TEST VALUES('XYZ1004'); -- Bad data

-

-- Data in the table
SELECT * FROM TEST;

Выход

enter image description here

-- You need to create your view as following
-- rownum is used so that WHERE clause of view is executed first 
-- and then any external WHERE clause on the view is executed 
CREATE OR REPLACE VIEW ABC_NEWVIEW AS
    SELECT
        ID
    FROM
        (
            SELECT
                CAST(SUBSTR(T_ID, 3, 100) AS NUMBER) AS ID,
                ROWNUM RN
            FROM
                TEST
            WHERE
                CASE
                    WHEN TRIM(TRANSLATE(SUBSTR(T_ID, 3, 100), '0123456789-,.', ' ')) IS NULL THEN 'numeric'
                    ELSE 'alpha'
                END = 'numeric'
        )

-

-- View
SELECT * FROM ABC_NEWVIEW

Выход

enter image description here

-- Query using WHERE condition
SELECT *
FROM ABC_NEWVIEW
WHERE 
ID = 1001

Выход

enter image description here

Демонстрацию можно найти по следующей ссылке:

Демонстрация DB Fiddle

Демонстрацию VIEW можно посмотреть без ROWNUM: ВоспроизведеноВаша проблема - Так что проблема заключается в порядке исполнения.

Ура !!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...