Pregunta

Mi jefe encontró un error en una consulta que creé y no entiendo el razonamiento detrás del error, aunque los resultados de la consulta demuestran que tiene razón.Aquí está la consulta (versión simplificada) antes de la solución:

select PTNO,PTNM,CATCD
from PARTS 
left join CATEGORIES on (CATEGORIES.CATCD=PARTS.CATCD); 

y aquí está después de la corrección:

select PTNO,PTNM,PARTS.CATCD
from PARTS 
left join CATEGORIES on (CATEGORIES.CATCD=PARTS.CATCD); 

El error fue que se mostraban valores nulos para la columna CATCD, es decir.los resultados de la consulta incluyeron resultados de la tabla CATEGORÍAS en lugar de PIEZAS.Esto es lo que no entiendo:Si había ambigüedad en la consulta original, ¿por qué Oracle no arrojó un error?Según tengo entendido, en el caso de uniones izquierdas, la tabla "principal" de la consulta (PARTS) tiene prioridad en cuanto a ambigüedad.¿Me equivoco o simplemente no pienso correctamente en este problema?

Actualizar:

Aquí hay un ejemplo revisado, donde no se genera el error de ambigüedad:

CREATE TABLE PARTS (PTNO NUMBER, CATCD NUMBER, SECCD NUMBER);

CREATE TABLE CATEGORIES(CATCD NUMBER);

CREATE TABLE SECTIONS(SECCD NUMBER, CATCD NUMBER);


select PTNO,CATCD 
from PARTS 
left join CATEGORIES on (CATEGORIES.CATCD=PARTS.CATCD) 
left join SECTIONS on (SECTIONS.SECCD=PARTS.SECCD) ;

¿Alguien tiene una idea?

¿Fue útil?

Solución

Me temo que no puedo decirle por qué no obtiene una excepción, pero puedo postular por qué eligió la versión de la columna de CATEGORÍAS en lugar de la versión de PIEZAS.

Según tengo entendido, en el caso de combinaciones izquierdas, la tabla "principal" de la consulta (PARTS) tiene prioridad en términos de ambigüedad.

No está claro si por "principal" te refieres simplemente a la tabla izquierda en una combinación izquierda o a la tabla "controladora", como ves la consulta conceptualmente...Pero en cualquier caso, lo que ve como la tabla "principal" en la consulta tal como la escribió no será necesariamente la tabla "principal" en la ejecución real de esa consulta.

Supongo que Oracle simplemente está usando la columna de la primera tabla que encuentra al ejecutar la consulta.Y dado que la mayoría de las operaciones individuales en SQL no requieren que se acceda a una tabla antes que a la otra, el DBMS decidirá en el momento del análisis cuál es la más eficiente para escanear primero.Intente obtener un plan de ejecución para la consulta.Sospecho que puede revelar que está presionando CATEGORÍAS primero y luego PIEZAS.

Otros consejos

Aquí está la consulta (versión simplificada)

Creo que al simplificar la consulta eliminaste la causa real del error :-)

¿Qué versión de Oracle estás usando?Oracle 10g (10.2.0.1.0) proporciona:

create table parts (ptno number , ptnm number , catcd number);  
create table CATEGORIES (catcd number);

select PTNO,PTNM,CATCD from PARTS  
left join CATEGORIES on (CATEGORIES.CATCD=PARTS.CATCD);

Obtengo ORA-00918:columna ambiguamente definida

Interesante en el servidor SQL que arroja un error (como debería)

select id
from sysobjects s
left join syscolumns c on s.id = c.id

Servidor:MSG 209, Nivel 16, Estado 1, Línea 1 Nombre de la columna ambigua 'ID'.

select id
from sysobjects 
left join syscolumns  on sysobjects.id = syscolumns.id

Servidor:MSG 209, Nivel 16, Estado 1, Línea 1 Nombre de la columna ambigua 'ID'.

Según mi experiencia, si crea una consulta como esta, el resultado de los datos extraerá CATCD del lado derecho de la unión, no del izquierdo, cuando hay una superposición de campos como este.

Entonces, dado que esta unión tendrá todos los registros de PARTES con solo algunos extractos de CATEGORÍAS, tendrá NULL en el campo CATCD cada vez que no haya datos en el lado derecho.

Al definir explícitamente la columna desde PARTS (es decir, el lado izquierdo), obtendrá un valor no nulo suponiendo que el campo tiene datos en PARTS.

Recuerde que con LEFT JOIN solo tiene garantizados los datos en los campos de la tabla de la izquierda, es posible que haya columnas vacías a la derecha.

Esto puede ser un error en el optimizador de Oracle.Puedo reproducir el mismo comportamiento en la consulta con 3 tablas.Intuitivamente parece que debería producir un error.Si lo reescribo de cualquiera de las siguientes maneras, genera un error:

(1) Uso de unión exterior de estilo antiguo

select ptno, catcd
from parts, categories, sections
where categories.catcd (+) = parts.catcd
  and sections.seccd (+) = parts.seccd

(2) Aislar explícitamente las dos uniones

select ptno, catcd
from (
  select ptno, seccd, catcd
  from parts
  left join categories on (categories.CATCD=parts.CATCD) 
)
left join sections on (sections.SECCD=parts.SECCD)

Utilicé DBMS_XPLAN para obtener detalles sobre la ejecución de la consulta, lo que mostró algo interesante.El plan es básicamente unir externamente PIEZAS y CATEGORÍAS, proyectar ese conjunto de resultados y luego unirlo externamente a SECCIONES.Lo interesante es que en la proyección de la primera unión externa, solo incluye PTNO y SECCD; NO incluye el CATCD de ninguna de las dos primeras tablas.Por lo tanto el resultado final es obtener CATCD de la tercera tabla.

Pero no sé si esto es una causa o un efecto.

Estoy usando Oracle 9.2.0.8.0.y da el error "ORA-00918:columna ambiguamente definida".

Este es un error conocido en algunas versiones de Oracle cuando se utilizan combinaciones de estilo ANSI.El comportamiento correcto sería obtener un error ORA-00918.

Siempre es mejor especificar los nombres de las tablas de todos modos;de esa manera sus consultas no se interrumpen cuando agrega una nueva columna con un nombre que también se usa en otra tabla.

En general, se recomienda ser específico y calificar completamente todos los nombres de las columnas de todos modos, ya que le ahorra un poco de trabajo al optimizador.Ciertamente en SQL Server.

Por lo que puedo deducir del Documentos de Oracle, parece que solo se generará si selecciona el nombre de la columna dos veces en la lista de selección, o una vez en la lista de selección y luego nuevamente en otro lugar, como una cláusula de orden por.

Quizás hayas descubierto una "característica no documentada" :)

Al igual que HollyStyles, no puedo encontrar nada en los documentos de Oracle que pueda explicar lo que estás viendo.

PostgreSQL, DB2, MySQL y MSSQL se niegan a ejecutar la primera consulta porque es ambigua.

@Palmadita:Recibo el mismo error aquí para su consulta.Mi consulta es un poco más complicada que la que publiqué originalmente.Estoy trabajando en un ejemplo simple reproducible ahora.

Una pregunta más importante que debería hacerse es: ¿por qué tengo un código de categoría en la tabla de piezas que no existe en la tabla de categorías?

Este es un error en Oracle 9i.Si une más de 2 tablas usando la notación ANSI, no detectará ambigüedades en los nombres de las columnas y puede devolver la columna incorrecta si no se usa un alias.

Como ya se mencionó, está arreglado en 10g, por lo que si no se usa un alias, se devolverá un error.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top