ORA-01722: недопустимый номер только при выборе * из представления, а не против просмотра напрямую

Я получаю сообщение ORA-01722: неверный номер, но только когда я select * from theView, но не когда я выбираю непосредственно представление (используя SQL внутри представления CREATE OR REPLACE...).

(Я сталкивался с этой ошибкой и понимаю ее раньше, а также выполнял агрегаты для значений NULL, что нельзя хранить VARCHARS в столбцах NUMBER и т. д., но я изо всех сил пытаюсь понять эту проблему)


person mrcrag    schedule 25.08.2020    source источник
comment
Имеют ли представление и таблица одинаковые типы данных столбцов? Была ли таблица изменена недавно?   -  person Jonathan Jacobson    schedule 25.08.2020
comment
Таблица не была изменена, но только определенные запросы вызывают проблему (включая случай, который я сейчас использую для отладки). Нет, sql - это беспорядок (два UNION ALL и множество приведений (to_number(to_char(RSQR,'9.99EEEE')) AS RSQR)...   -  person mrcrag    schedule 25.08.2020


Ответы (1)


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

Простой пример:

create table t as
     select '1' x, 'num' xtype from dual union all
     select 'A' x, 'str' xtype from dual
/
create index t_ind on t(x);

Вы можете видеть, что в этом очень простом примере мы получаем ORA-01722, несмотря на то, что мы указали фильтр xtype='num' перед x > 0:

select x
from (
     select x
     from t
     where xtype='num'
     ) v
where v.x > 0;

ERROR:
ORA-01722: invalid number

План выполнения:

Plan hash value: 1601196873

---------------------------------------------------------------------------
| Id  | Operation         | Name | E-Rows |E-Bytes| Cost (%CPU)| E-Time   |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |        |       |     3 (100)|          |
|*  1 |  TABLE ACCESS FULL| T    |      1 |     6 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SEL$F5BB74E1 / T@SEL$2

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter((TO_NUMBER("X")>0 AND "XTYPE"='num'))

Как видно из плана, встроенное представление было merged и оба предиката находятся на одном уровне.

Теперь сравните с этим:

select/*+ 
           no_merge(v) 
           opt_param('_optimizer_filter_pushdown' 'false')
     */ 
      x
from (
     select x
     from t
     where xtype='num'
     ) v
where v.x > 0;

X
-
1

План выполнения:

Plan hash value: 3578092569

----------------------------------------------------------------------------
| Id  | Operation          | Name | E-Rows |E-Bytes| Cost (%CPU)| E-Time   |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |        |       |     3 (100)|          |
|*  1 |  VIEW              |      |      1 |     3 |     3   (0)| 00:00:01 |
|*  2 |   TABLE ACCESS FULL| T    |      1 |     6 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SEL$2 / V@SEL$1
   2 - SEL$2 / T@SEL$2

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(TO_NUMBER("V"."X")>0)
   2 - filter("XTYPE"='num')

Подробнее об этом: http://orasql.org/2013/06/10/too-many-function-executions/

person Sayan Malakshinov    schedule 25.08.2020
comment
Интересно. Спасибо. Я попытаюсь обновить порядок столбцов (и, возможно, порядок предложения объединения). - person mrcrag; 25.08.2020