Oracle möglich SOFORT mit variablen Anzahl von bindet EXECUTE?
-
06-07-2019 - |
Frage
Ich brauche dynamische SQL-Ausführung auf Oracle verwenden, wo ich weiß nicht, die genaue Anzahl der Bind-Variablen in der SQL vor der Laufzeit verwendet wird.
Gibt es eine Möglichkeit, eine variable Anzahl von Bind-Variablen im Aufruf zu verwenden, irgendwie EXECUTE IMMEDIATE
?
Insbesondere muss ich passieren ein Parameter in das Unbekannte SQL, aber ich weiß nicht, wie oft wird es dort verwendet werden.
Ich habe versucht, so etwas wie
EXECUTE IMMEDIATE 'SELECT SYSDATE FROM DUAL WHERE :var = :var' USING 1;
Aber es warf zurück mit ORA-01008: not all variables bound.
Lösung
Sie können dies nicht mit EXECUTE IMMEDIATE
. Allerdings können Sie dies tun, indem Oracle DBMS_SQL
Paket. Die Database Application Developer Guide hat ein Vergleich zwischen dem EXECUTE IMMEDIATE
Sie mit und dbms_sql
Methoden vertraut sind. Diese Seite Dokumente DBMS_SQL
, aber hat einige Beispiele (oben verlinkten), die Sie (Beispiel 1 ist ein einfacher Fall von einer Anweisung ausgeführt wird, die eine beliebige Anzahl von bind-Variablen haben könnte) beginnen sollte. DBMS_SQL
ist viel umständlicher aus einer Codierung Perspektive, aber es ermöglicht es Ihnen, nur um etwas zu tun, können Sie sich vorstellen.
Mehrere Instanzen der Bind Variable in der SQL auftreten darf. Allerdings müssen Sie den Namen kennen, als Bindevariable verwendet werden (zum Beispiel: var in Ihrem Fall)., Um es in DBMS_SQL.BIND_VARIABLE
passiert
Andere Tipps
Sie können auch durch die Verwendung einer WITH
Anweisung, um dieses Problem zu umgehen. Im Allgemeinen mit DBMS_SQL
ist besser, aber manchmal ist dies ein einfacher Weg:
BEGIN
EXECUTE IMMEDIATE 'WITH var AS (SELECT :var FROM dual) SELECT SYSDATE FROM DUAL WHERE (SELECT * FROM var) = (SELECT * FROM var)' USING 1;
END;
Das Thread auf AskTom deckt das Thema im Detail
In Ihrem Fall, wenn Sie einen Parameter oder keine übergeben möchten, können Sie zwei Abfragen erstellen, die einen einzelnen Parameter haben und in einem dieser Abfrage nicht verwendet wird (dh das Prädikat ist immer wahr) wie folgt aus:
-- query1
SELECT * FROM DUAL WHERE dummy = :x;
-- query2
SELECT * FROM DUAL WHERE nvl(:x, 1) IS NOT NULL;
Sie können sich wahrscheinlich das Prädikat verfeinern, so dass das Optimierungsprogramm wird verstehen, dass es immer wahr ist.
Genauer gesagt, ich brauche einen Parameter in das Unbekannte SQL passieren, aber ich weiß nicht, wie oft wird es dort verwendet werden.
Ich lief tatsächlich in dieses exakt gleiche Problem vor ein paar Tagen, und ein Freund mit mir geteilt, einen Weg, genau das mit EXECUTE IMMEDIATE
zu tun.
Es geht um Erzeugen eines PLSQL Block in Bezug auf die SQL-Block selbst gegenüber. Wenn EXECUTE IMMEDIATE
mit einem Block von PLSQL Code verwenden, können Sie Variablen mit Namen binden im Gegensatz zu nur durch Position.
überprüfen Sie mein Beispiel / Code und auf meinem eigenen ähnlichen Frage / Antwort-Thread:
Man kann dbms_sql
wie Steve Broberg verwenden erklärt aber die resultierende Cursor kann (lesen) in einer Menge von Kunden nicht verzehrt werden. Oracle 11 hat eine Konvertierungsfunktion ( dbms_sql.to_refcursor
), der es ermöglicht, eine dbms_sql
Cursor auf einen ref Cursor zu konvertieren, aber man kann nicht verbrauchen diese ref Cursor in einer .Net-Anwendung aus irgendeinem Grunde umgewandelt. Man kann eine normale ref Cursor in .net verbraucht aber keine ref Cursor, die dbms_sql
Cursor verwendet werden, um.
Also, welche Art von Client raubend diesen Cursor sein?