ora oci_execute invalid error sql oracle alias decode ora-00904

sql - oci_execute - Usar un alias en una cláusula WHERE



oci_execute() ora 00904 invalid identifier (5)

Tengo una consulta que debe mostrarme las filas de la tabla A que no se han actualizado lo suficiente. (Cada fila debe actualizarse dentro de los 2 meses posteriores a "mes_no"):

SELECT A.identifier , A.name , TO_NUMBER(DECODE( A.month_no , 1, 200803 , 2, 200804 , 3, 200805 , 4, 200806 , 5, 200807 , 6, 200808 , 7, 200809 , 8, 200810 , 9, 200811 , 10, 200812 , 11, 200701 , 12, 200702 , NULL)) as MONTH_NO , TO_NUMBER(TO_CHAR(B.last_update_date, ''YYYYMM'')) as UPD_DATE FROM table_a A , table_b B WHERE A.identifier = B.identifier AND MONTH_NO > UPD_DATE

La última línea en la cláusula WHERE provoca un error "ORA-00904 Identificador no válido". Huelga decir que no quiero repetir toda la función DECODE en mi cláusula WHERE. ¿Alguna idea? (Ambas correcciones y soluciones temporales aceptadas ...)


Es posible definir efectivamente una variable que se puede usar tanto en las cláusulas SELECT, WHERE como en otras.

Una subconsulta no necesariamente permite un enlace apropiado a las columnas de tabla referenciadas, sin embargo, lo hace OUTER APPLY.

SELECT A.identifier , A.name , vars.MONTH_NO , TO_NUMBER(TO_CHAR(B.last_update_date, ''YYYYMM'')) as UPD_DATE FROM table_a A , table_b B ON A.identifier = B.identifier OUTER APPLY ( SELECT -- variables MONTH_NO = TO_NUMBER(DECODE( A.month_no , 1, 200803 , 2, 200804 , 3, 200805 , 4, 200806 , 5, 200807 , 6, 200808 , 7, 200809 , 8, 200810 , 9, 200811 , 10, 200812 , 11, 200701 , 12, 200702 , NULL)) ) vars WHERE vars.MONTH_NO > UPD_DATE

Felicitaciones a Syed Mehroz Alam .


Esto no es posible directamente, porque cronológicamente, WHERE sucede antes de SELECT, que siempre es el último paso en la cadena de ejecución.

Puede hacer una selección secundaria y filtrar en ella:

SELECT * FROM ( SELECT A.identifier , A.name , TO_NUMBER(DECODE( A.month_no , 1, 200803 , 2, 200804 , 3, 200805 , 4, 200806 , 5, 200807 , 6, 200808 , 7, 200809 , 8, 200810 , 9, 200811 , 10, 200812 , 11, 200701 , 12, 200702 , NULL)) as MONTH_NO , TO_NUMBER(TO_CHAR(B.last_update_date, ''YYYYMM'')) as UPD_DATE FROM table_a A , table_b B WHERE A.identifier = B.identifier ) AS inner_table WHERE MONTH_NO > UPD_DATE

Un poco de información interesante pasó de los comentarios a:

No debería haber ningún golpe de rendimiento. Oracle no necesita materializar consultas internas antes de aplicar condiciones externas: Oracle considerará transformar esta consulta internamente y empujará el predicado hacia abajo en la consulta interna y lo hará si es rentable. - Justin Cave


O puede tener su alias en una cláusula HAVING


Tal como lo puede hacer un enfoque alternativo para usted:

WITH inner_table AS (SELECT A.identifier , A.name , TO_NUMBER(DECODE( A.month_no , 1, 200803 , 2, 200804 , 3, 200805 , 4, 200806 , 5, 200807 , 6, 200808 , 7, 200809 , 8, 200810 , 9, 200811 , 10, 200812 , 11, 200701 , 12, 200702 , NULL)) as MONTH_NO , TO_NUMBER(TO_CHAR(B.last_update_date, ''YYYYMM'')) as UPD_DATE FROM table_a A , table_b B WHERE A.identifier = B.identifier) SELECT * FROM inner_table WHERE MONTH_NO > UPD_DATE

También puede crear una vista permanente para su cola y seleccionar desde la vista.

CREATE OR REPLACE VIEW_1 AS (SELECT ...); SELECT * FROM VIEW_1;


SELECT A.identifier , A.name , TO_NUMBER(DECODE( A.month_no , 1, 200803 , 2, 200804 , 3, 200805 , 4, 200806 , 5, 200807 , 6, 200808 , 7, 200809 , 8, 200810 , 9, 200811 , 10, 200812 , 11, 200701 , 12, 200702 , NULL)) as MONTH_NO , TO_NUMBER(TO_CHAR(B.last_update_date, ''YYYYMM'')) as UPD_DATE FROM table_a A, table_b B WHERE .identifier = B.identifier HAVING MONTH_NO > UPD_DATE