2011-10-19 49 views
38

Tengo una pregunta sobre dónde se pueden usar las variables de vinculación en una sentencia de SQL dinámico en PL/SQL.Uso de variables de vinculación con la cláusula dinámica SELECT INTO en PL/SQL

Por ejemplo, sé que esto es válido:

CREATE OR REPLACE FUNCTION get_num_of_employees (p_loc VARCHAR2, p_job VARCHAR2) 
RETURN NUMBER 
IS 
    v_query_str VARCHAR2(1000); 
    v_num_of_employees NUMBER; 
BEGIN 
    v_query_str := 'SELECT COUNT(*) FROM emp_' 
       || p_loc 
       || ' WHERE job = :bind_job';       
    EXECUTE IMMEDIATE v_query_str 
    INTO v_num_of_employees 
    USING p_job; 
    RETURN v_num_of_employees; 
END; 
/

Me preguntaba si usted podría utilizar una variables se unen en una instrucción de selección como esta

CREATE OR REPLACE FUNCTION get_num_of_employees (p_loc VARCHAR2, p_job VARCHAR2) 
RETURN NUMBER 
IS 
    v_query_str VARCHAR2(1000); 
    v_num_of_employees NUMBER; 
BEGIN 
    v_query_str := 'SELECT COUNT(*) INTO :into_bind FROM emp_' 
       || p_loc 
       || ' WHERE job = :bind_job';       
    EXECUTE IMMEDIATE v_query_str 
    USING out v_num_of_employees, p_job; 
    RETURN v_num_of_employees; 
END; 
/

Nota he usado un SELECT INTO declaración como mi cadena dyamic y utilizó una variable de vinculación en la cláusula INTO.

Actualmente estoy de viaje y no tendré acceso a mi computadora en mi casa por unos días, pero esto me ha estado molestando un poco. Intenté leer la referencia PL/SQL, pero no tienen un ejemplo de una selección como esta.

Gracias

+0

Relacionados: http://stackoverflow.com/q/25489002/1461424 – Krumia

Respuesta

24

No, no puede usar las variables de vinculación de esa manera. En su segundo ejemplo :into_bind en v_query_str es solo un marcador de posición para el valor de la variable v_num_of_employees. Su select into se convertirá en algo así como:

SELECT COUNT(*) INTO FROM emp_... 

porque el valor de v_num_of_employees es null en EXECUTE IMMEDIATE.

Su primer ejemplo presenta la forma correcta de enlazar el valor de retorno a una variable.

Editar

El cartel original ha editado el segundo bloque de código que me refiero en mi respuesta a utilizar OUT modo de parámetro para v_num_of_employees en lugar del modo por defecto IN. Esta modificación hace que los dos ejemplos sean funcionalmente equivalentes.

+0

Oh, eso tiene sentido, el ': into_bind' sería reemplazado cuando en realidad se ejecuta. En el primer ejemplo que escribí, ¿seguiría usando una variable de vinculación en la cláusula INTO? La razón por la que quería probar la segunda forma fue porque usa variables de vinculación. – BYS2

+2

@ BYS2: Sí, puede usar el modo de parámetro 'OUT'. Sin embargo, prefiero 'EJECUTAR INMEDIATE INTO' para mayor claridad. – user272735

+0

¡Oh bien, genial, así que también funciona! bien, gracias :) – BYS2

18

Coloque la instrucción de selección en un bloque dinámico PL/SQL.

CREATE OR REPLACE FUNCTION get_num_of_employees (p_loc VARCHAR2, p_job VARCHAR2) 
RETURN NUMBER 
IS 
    v_query_str VARCHAR2(1000); 
    v_num_of_employees NUMBER; 
BEGIN 
    v_query_str := 'begin SELECT COUNT(*) INTO :into_bind FROM emp_' 
       || p_loc 
       || ' WHERE job = :bind_job; end;'; 
    EXECUTE IMMEDIATE v_query_str 
    USING out v_num_of_employees, p_job; 
    RETURN v_num_of_employees; 
END; 
/
+0

Ahh veo, gracias! En una nota lateral, ¿tienes alguna idea de qué camino es mejor? encapsulando SELECT INTO en un bloque como lo hizo o usando la cláusula INTO de la sentencia EXECUTE IMMEDIATE como hice en mi primer ejemplo. ¿Ambos usan variables de vinculación? cualquier diferencia en la eficiencia? – BYS2

+1

Estoy de acuerdo con los demás en que el primer método (SQL dinámico) es mucho mejor que el segundo (PL/SQL dinámico). Dinámico PL/SQL es muy raro y casi nunca es necesario. Basado en algunas pruebas simples, no vi ninguna diferencia de rendimiento entre los dos, pero esperaría que el método dinámico PL/SQL fuera un poco más lento en algunos casos. El método dinámico PL/SQL en realidad genera 3 variables de enlace: 2 para el bloque PL/SQL (aunque ninguno se captura en V $ SQL_BIND_CAPTURE) y 1 para la consulta SQL. Los errores de ese tipo pueden dificultar el ajuste y la depuración. –

+0

¡Oh bien, muchas gracias por todos sus consejos! No pude mencionar la respuesta porque técnicamente, esa no era mi pregunta, pero estoy dispuesto a aprender, así que es bueno saber: D – BYS2

24

En mi opinión, un bloque PL/SQL dinámico es algo oscuro. Si bien es muy flexible, también es difícil de sintonizar, difícil de depurar y difícil de descifrar qué ocurre. Mi voto va a su primera opción,

EXECUTE IMMEDIATE v_query_str INTO v_num_of_employees USING p_job; 

ambos usos variables se unen, pero en primer lugar, para mí, es más redeable y sintonizable opción de @jonearles.

+0

Ok gracias por esa información, ya que ambos usan varialbes bind, ¡la primera opción parece ser la mejor! – BYS2

+1

@ BYS2: también me gusta mejor esta sintaxis. No tengo idea del rendimiento. – user272735

0

La variable de vinculación se puede utilizar en la consulta SQL de Oracle con la cláusula "in".

Funciona en 10g; No sé sobre otras versiones.

La variable de enlace es varchar hasta 4000 caracteres.

Ejemplo: variable de vinculación que contiene una lista de valores separados por comas, p.

: bindvar = 1,2,3,4,5

select * from mytable 
    where myfield in 
    (
     SELECT regexp_substr(:bindvar,'[^,]+', 1, level) items 
     FROM dual 
     CONNECT BY regexp_substr(:bindvar, '[^,]+', 1, level) is not null 
    ); 

(misma información que he publicado aquí: How do you specify IN clause in a dynamic query using a variable?)

-2

select into funcionalidad sólo funciona para PL/SQL bloque, cuando se use Execute immediate, oracle interpreta v_query_str como una cadena de consulta SQL para que no pueda usar .will get keyword missing Exception. en el ejemplo 2, estamos utilizando begin end; por lo que se convirtió en bloque pl/sql y es legal.

Cuestiones relacionadas