sql >> Base de Datos >  >> RDS >> Oracle

cláusula de unión en sql

Esta respuesta puede ser un poco incoherente...

Oracle es muy exigente con las operaciones establecidas. Cada columna debe tener el mismo tipo de datos que las correspondientes en la segunda, tercera, etc. consultas.

yo creo su segunda consulta falla porque Oracle evalúa to_number() como un número anterior para realizar la union pero lo evalúa como "null-ness" después . Su primera consulta tuvo éxito porque el primer valor se evaluó para "null-ness" y luego la union ocurre. Esto implica que el orden de evaluación es:

  1. Primeras funciones seleccionadas
  2. Primer tipo de datos seleccionados
  3. Segunda función de selección
  4. sindicato
  5. Segundo tipo de datos seleccionados

Intentaré probar esto paso a paso, pero no estoy seguro de que llegue a ser una prueba absoluta.

Las dos consultas siguientes

select 1 from dual union select '1' from dual;
select '1' from dual union select 1 from dual;

fallará con el siguiente error ya que no se lleva a cabo ninguna conversión implícita.

Sin embargo, los dos siguientes tendrán éxito

select null from dual union select '1' from dual;
select null from dual union select 1 from dual;

Si seleccionamos el dump de estas dos consultas se devuelve lo siguiente:

SQL> select dump(a)
  2    from ( select null a from dual union select '1' from dual );

DUMP(A)
-------------------------------------------------------------------

Typ=96 Len=1: 49
NULL

SQL> select dump(a)
  2    from ( select null a from dual union select 1 from dual );

DUMP(A)
-------------------------------------------------------------------

Typ=2 Len=2: 193,2
NULL

Como puede ver, las columnas tienen diferentes tipos de datos . La primera consulta, con un carácter, devuelve un char y el segundo devuelve un número, pero el orden se ha invertido, con el segundo select viniendo primero.

Por último, si observamos dump de tu primera consulta

SQL> select substr(dump(ename),1,35) a, substr(dump(loc),1,35) b
  2    from ( select ename,to_number(null) as loc from emp
  3            union
  4           select to_char(null),loc from dept
  5                  );

A                                   B
----------------------------------- -----------------------------------
Typ=1 Len=6: 104,97,104,97,104,97   NULL
NULL                                Typ=1 Len=6: 104,97,104,97,104,97

SQL>

Puedes ver que dump(to_number(null)) es nulo; pero un varchar2 no es un char se devuelve, porque este es el tipo de datos de su columna. Es interesante notar que el orden de las declaraciones devueltas no se ha invertido y que si tuviera que crear esta consulta como una tabla, ambas columnas serían varchar2 .

Al decidir el tipo de datos de una columna en una consulta de selección, Oracle toma el primer tipo de datos conocido y luego lo usa para calcular el tipo de datos general. Esta sería la razón por la cual las consultas donde el primer select fue nulo tenían sus filas invertidas.

Su primera consulta tiene éxito porque la primera selección, select ename,to_number(null) from emp , "describe" cómo se verá el conjunto de resultados. |varchar2|null| . La segunda consulta luego agrega, |varchar2|varchar2| , que no causa problemas.

Su segunda consulta falla porque la primera selección select ename,to_number(null) from emp "describe" el conjunto de resultados como varchar2, null . Sin embargo, luego intenta agregar un número nulo y un varchar2 en la union .

El acto de fe aquí es que Oracle está decidiendo que to_number(null) es un número anterior al union y no evaluarlo por "nulidad" hasta después. Realmente no sé cómo probar si esto realmente está sucediendo, ya que no puedes crear un objeto con un null columna y como observas tampoco puedes seleccionarla.

Como no puedo probar algo que Oracle no permite, intentaré obtener evidencia empírica. Considere los resultados (o errores) de las siguientes consultas.

SQL> select 1 as a from dual union select to_number(null) from dual;

         A
----------
         1


SQL> select '1' as a from dual union select to_number(null) from dual;
select '1' as a from dual union select to_number(null) from dual
       *
ERROR at line 1:
ORA-01790: expression must have same datatype as corresponding expression


SQL> select 1 as a from dual union select to_char(null) from dual;
select 1 as a from dual union select to_char(null) from dual
       *
ERROR at line 1:
ORA-01790: expression must have same datatype as corresponding expression


SQL> select '1' as a from dual union select to_char(null) from dual;

A
-
1

Parecen demostrar que to_char y to_number , sin importar si se realizan en un nulo, definen implícitamente un tipo de datos que luego se evalúa para determinar su idoneidad en una union , antes de su evaluación de "nulidad"

Esta explicación también cubriría la coalesce problema como to_number(null) es un número antes de es un nulo.