Pregunta

Necesito usar la ejecución dinámica de SQL en Oracle, donde no sé el número exacto de variables de enlace utilizadas en el SQL antes del tiempo de ejecución.

¿Hay alguna manera de usar un número variable de variables de enlace en la llamada a EJECUTAR INMEDIATO de alguna manera?

Más específicamente, necesito pasar el parámetro uno al SQL desconocido, pero no sé con qué frecuencia se usará allí.

Intenté algo como

EXECUTE IMMEDIATE 'SELECT SYSDATE FROM DUAL WHERE :var = :var' USING 1;

Pero arrojó de nuevo con ORA-01008: no todas las variables vinculadas.

¿Fue útil?

Solución

No puede hacer esto con EJECUTAR INMEDIATO . Sin embargo, puede hacerlo utilizando el paquete DBMS_SQL de Oracle. La Guía del desarrollador de aplicaciones de bases de datos ha una comparación entre EJECUTAR INMEDIATO con el que está familiarizado y los métodos dbms_sql . Esta página documenta DBMS_SQL , pero tiene algunos ejemplos (vinculados anteriormente) que deberían ayudarlo a comenzar (el ejemplo 1 es un caso simple de ejecutar una declaración que podría tener un número arbitrario de variables de enlace). DBMS_SQL es mucho más engorroso desde una perspectiva de codificación, pero le permitirá hacer casi cualquier cosa que pueda concebir.

Se permiten varias instancias de la variable de enlace que se producen en el SQL. Sin embargo, deberá conocer el nombre que se utiliza como variable de enlace (por ejemplo, var en su caso) para pasarlo a DBMS_SQL.BIND_VARIABLE .

Otros consejos

También podría solucionar este problema utilizando una instrucción WITH . Generalmente, usar DBMS_SQL es mejor, pero a veces esta es una forma más simple:

BEGIN
    EXECUTE IMMEDIATE 'WITH var AS (SELECT :var FROM dual) SELECT SYSDATE FROM DUAL WHERE (SELECT * FROM var) = (SELECT * FROM var)' USING 1;
END;

Esto Tema en AskTom cubre el tema en detalles.

En su caso, si desea pasar un parámetro o ninguno, puede crear dos consultas que tengan un solo parámetro y en una de estas consultas no se usa (es decir, el predicado siempre es verdadero) como este:

-- query1
SELECT * FROM DUAL WHERE dummy = :x;

-- query2
SELECT * FROM DUAL WHERE nvl(:x, 1) IS NOT NULL;

Probablemente pueda refinar el predicado para que el optimizador entienda que siempre es cierto.

  

Más específicamente, necesito pasar un parámetro al SQL desconocido, pero no sé con qué frecuencia se usará allí.

En realidad, me encontré con este mismo problema hace un par de días, y un amigo compartió conmigo una forma de hacer exactamente eso con EJECUTAR INMEDIATO .

Implica generar un bloque PLSQL en lugar del bloque SQL mismo. Al usar EJECUTAR INMEDIATO con un bloque de código PLSQL, puede vincular variables por nombre en lugar de solo por posición.

Echa un vistazo a mi ejemplo / código y en mi propio hilo similar de preguntas / respuestas:

Se puede usar dbms_sql como Steve Broberg explicó, pero el cursor resultante no se puede consumir (leer) en muchos clientes. Oracle 11 ha agregado una función de conversión ( dbms_sql .to_refcursor ) que hace posible convertir un cursor dbms_sql en un cursor de referencia, pero por alguna razón no se puede consumir este cursor de referencia convertido en una aplicación .Net. Uno puede consumir un cursor de referencia normal en .net pero no un cursor de referencia que solía ser el cursor dbms_sql .

Entonces, ¿qué tipo de cliente consumirá este cursor?

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