Mezclar JOIN implícitas y explícitas
Tengo un problema con Hibernate que genera SQL no válido. Específicamente, mezclar y combinar uniones implícitas y explícitas. Esto parece ser un error abierto .
Sin embargo, no estoy seguro de por qué este SQL no es válido. Se me ocurrió un pequeño ejemplo de juguete que genera la misma excepción de sintaxis.
Esquema
CREATE TABLE Employee (
employeeID INT,
name VARCHAR(255),
managerEmployeeID INT
)
Datos
INSERT INTO Employee (employeeID, name) VALUES (1, 'Gary')
INSERT INTO Employee (employeeID, name, managerEmployeeID) VALUES (2, 'Bob', 1)
SQL de trabajo
Ambas consultas funcionan. Me doy cuenta de que hay un producto cartesiano; eso es intencional.
UNIRSE explícitamente:
SELECT e1.name,
e2.name,
e1Manager.name
FROM Employee e1
CROSS JOIN Employee e2
INNER JOIN Employee e1Manager
ON e1.managerEmployeeID = e1Manager.employeeID
UNIRSE implícitamente:
SELECT e1.name,
e2.name,
e1Manager.name
FROM Employee e1,
Employee e2,
Employee e1Manager
WHERE e1.managerEmployeeID = e1Manager.employeeID
SQL no válido
Esta consulta NO funciona en MSSQL 2000/2008 o MySQL:
SELECT e1.name,
e2.name,
e1Manager.name
FROM Employee e1,
Employee e2
INNER JOIN Employee e1Manager
ON e1.managerEmployeeID = e1Manager.employeeID
En MS2000, aparece el error:
El prefijo de columna 'e1' no coincide con el nombre de una tabla o el nombre de alias utilizado en la consulta.
En MySQL, el error es:
Columna desconocida 'e1.managerEmployeeID' en la 'cláusula on'.
Preguntas)
- ¿Por qué esta sintaxis no es válida?
- Bonificación: ¿Hay alguna forma de obligar a Hibernate a utilizar solo JOINs explícitos?
Da como resultado un error porque, según el estándar SQL, la JOIN
palabra clave tiene mayor prioridad que la coma. El problema es que los alias de tablas no se pueden utilizar hasta que la tabla correspondiente haya sido evaluada en la FROM
cláusula.
Entonces, cuando haces referencia e1
en tu JOIN...ON
expresión, e1
aún no existe.
Espere mientras investigo sobre Hibernate y averigüe si puede convencerlo para que lo utilice JOIN
en todos los casos.
Mmm. Todo en Hibernate.org parece redirigir a jboss.org. Así que no hay forma de leer la documentación HQL en línea en este momento. Estoy seguro de que eventualmente descubrirán su nombre.
Esto podría estar un poco fuera de tema, porque no tiene nada que ver con la hibernación, pero el comentario de Bill Karwin realmente me abrió los ojos. En lugar de escribir primero la unión implícita, primero debe realizar la unión explícita. Esta sintaxis es especialmente interesante si tiene varias combinaciones implícitas.
Consulte el siguiente ejemplo en MS SQL. No todos los contactos tienen un código de país definido, pero todos los contactos tienen un atributo val que se buscará en la tabla Tbl. Entonces la solución intuitiva no funcionará:
SELECT * FROM
contacts, Tbl
LEFT OUTER JOIN country ON CtryCod = country.CtryCod
WHERE val = Tbl.val
En su lugar, es posible que desee utilizar la siguiente sintaxis:
SELECT * FROM
contacts LEFT OUTER JOIN country ON CtryCod = country.CtryCod,
Tbl
WHERE val = Tbl.val