ORA-01722:在其中选择数字列和相同数字列引用时编号无效

时间:2019-06-25 06:09:46

标签: sql oracle

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 :(得分:0)

有两个问题:

  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 demo

您可以看到没有ROWNUM的VIEW演示: Reproduced your issue-因此,问题在于执行的顺序。

干杯!