it-swarm.com.de

Verwenden von Bindungsvariablen mit dynamischer SELECT INTO-Klausel in PL/SQL

Ich habe eine Frage, wo Bind-Variablen in einer dynamischen SQL-Anweisung in PL/SQL verwendet werden können.

Ich weiß zum Beispiel, dass dies gültig ist:

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;
/

Ich habe mich gefragt, ob Sie eine Bind-Variable in einer Select-Anweisung wie dieser verwenden könnten

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;
/

Hinweis Ich habe eine SELECT INTO-Anweisung als dyamic-Zeichenfolge und eine Bind-Variable in der INTO-Klausel verwendet.

Ich bin momentan im Moment unterwegs und habe für ein paar Tage keinen Zugang zu meinem Computer zu Hause, aber das hat mich ein bisschen gequält. Ich habe versucht, die PL/SQL-Referenz zu lesen, aber sie haben kein Beispiel für eine Auswahl wie diese.

Vielen Dank

42
BYS2

Nein, Sie können keine Bindungsvariablen auf diese Weise verwenden. In Ihrem zweiten Beispiel ist :into_bind in v_query_str nur ein Platzhalter für den Wert der Variablen v_num_of_employees. Ihre select-in-Anweisung wird wie folgt aussehen:

SELECT COUNT(*) INTO  FROM emp_...

weil der Wert von v_num_of_employeesnull bei EXECUTE IMMEDIATE ist.

Ihr erstes Beispiel zeigt die korrekte Methode, um den Rückgabewert an eine Variable zu binden.

Bearbeiten

Das ursprüngliche Poster hat den zweiten Codeblock, auf den ich in meiner Antwort verweise, so bearbeitet, dass der OUT-Parametermodus für v_num_of_employees anstelle des Standardmodells IN verwendet wird. Diese Modifikation macht die beiden Beispiele funktional gleichwertig.

27
user272735

Meiner Meinung nach ist ein dynamischer PL/SQL-Block etwas unklar. Während es sehr flexibel ist, ist es auch schwer zu stimmen, schwer zu debuggen und schwer herauszufinden, was los ist .. Meine Stimme fällt auf Ihre erste Option,

EXECUTE IMMEDIATE v_query_str INTO v_num_of_employees USING p_job;

Beide verwenden Bind-Variablen, aber zuerst ist sie für mich besser redigierbar und einstellbar als die Option @jonearles. 

27
Aitor

Setzen Sie die select-Anweisung in einen dynamischen PL/SQL-Block.

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;
/
18
Jon Heller

Die Bindungsvariable kann in der Oracle SQL-Abfrage mit der Klausel "in" verwendet werden.

Funktioniert in 10g; Ich kenne andere Versionen nicht.

Die Bindungsvariable ist varchar bis zu 4000 Zeichen.

Beispiel: Bindungsvariable mit durch Kommas getrennten Wertelisten, z.

: 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
    );

(Die gleichen Informationen, die ich hier gepostet habe: Wie geben Sie IN-Klauseln in einer dynamischen Abfrage mit einer Variablen an? )

0
Kat