Die WITH-Klausel ist ja eines der bestgehütesten Geheimnisse der Sprache SQL. In unseren Schulungen ernten wir immer wieder Erstaunen, wenn wir die Funktion vorstellen. Dabei ist sie schon seit einigen Oracle Versionen verfügbar.
Richtig spannend wurde es jedoch erst ab Version 12.x, doch dazu später mehr.
Schauen wir uns erst einmal die einfachste WITH-Klausel an:
Die WITH-Klausel ermöglicht uns, eine Ergebnismenge vorab zu aggregieren, um sie dann evtl. sogar mehrmals in einem SELECT wieder einzusetzen.
Hier wird die Query unter dem Namen "S" in Form einer Tabelle zur Verfügung gestellt. Nur hat die Ergebnismenge im ersten Fall halt nur eine Spalte und eine Zeile.
Ein Beispiel mit der EMP Tabelle darf natürlich nicht fehlen:
Ab Version 12.x können nun auch Proceduren und Funktionen in der WITH-Klausel verwendet werden. Erstaunlicherweise muss man dazu noch nicht mal ein "CREATE PROCEDURE" Recht besitzen. Ein Schelm, wer böses damit anstellt.
Manchmal möchte man auch einen Aufruf in SQL starten, der eigentlich nur in PL/SQL funktioniert,das ist mit der WITH-Klausel kein Problem.
Beispiel: Sie haben eine Fehlernummer von Oracle erhalten, aber nicht den Text. Der Versuch in SQL:
Mit der WITH-Klausel:
Oder mal eine komfortablere Datumskonvertierungsfunktion ...
Das geht auch mit Datumswerten wie: '01.01.01', '01-Mai.99', '30/DeC.2001', '02-jan:1932'. Das versuchen Sie mal mit der to_date Funktion ...
Auch mehrere WITH-Klauseln sind möglich:
Sie müssen sie nur mit einem Komma trennen.
Zum Schluss noch ein etwas anspruchsvolleres Beispiel, das wir gerne in den Kursen zeigen: Es soll ein Skript angelegt werden, das einen Benutzer mit all seinen zugewiesenen Rechten anzeigt.
Der Vorteil hier ist, dass man den Schemanamen in der WITH-Klausel, quasi wie eine Variable definieren kann, die man dann an mehreren Stellen weiter unten im SQL Statement wieder verwenden kann.
Nur kann es passieren, dass einer der Teil-Selects keine Ergebnismenge zurückbringt. Dieser ist dann so nett, mit dem Fehler ORA-31608 abzustürzen. Damit stürzt dann aber auch gleich das komplette SQL-Statement ab. Deswegen haben wir oben mit der COUNT Funktion geprüft, ob überhaupt Rechte vorhanden sind.
Ab 12c können wir aber auch das schöner lösen:
oder wollten Sie immer schon mal viele DDL befehle in einem Rutsch ausführen? Achtung die folgende Funktion löscht sofort alle invaliden Synonyme der Benutzer MDSYS und CTXSYS:
oder wollten Sie immer schon mal wissen, was der Parser aus Ihrem SQL Statement macht, bevor er loslegt?
WITH FUNCTION get_sql (p_sql IN CLOB) RETURN CLOB IS p_sql_out CLOB; BEGIN DBMS_UTILITY.EXPAND_SQL_TEXT (p_sql, p_sql_out); RETURN p_sql_out; END; select get_sql('select * from dual') from dual; /
oder interessieren Sie sich für Fehlertexte (Hier werden alle zwischen ORA-0100 und ORA-0200 angezeigt) in der Oracle Datenbank:
WITH FUNCTION get_err_text(id IN NUMBER) RETURN VARCHAR2 IS BEGIN return (sqlerrm(id)); END; err_msg as (SELECT rownum as err_id FROM dual CONNECT BY LEVEL<100000) SELECT get_err_text(-1*err_id) FROM err_msg WHERE err_id between 100 and 200;
oder möchten Sie den Längen und Breitengrad in den Oracle Spatial Dytentyp konvertieren?
WITH FUNCTION to_sdo ( lon IN NUMBER,lat IN NUMBER) RETURN SDO_GEOMETRY DETERMINISTIC IS geom SDO_GEOMETRY; BEGIN IF (lon BETWEEN -180 AND 180) AND (lat BETWEEN -90 AND 90) THEN RETURN SDO_GEOMETRY( 2001 -- 2-dimensionaler Punkt , 4326 -- SRID , SDO_POINT_TYPE( lon -- x-Koordinate , lat -- y-Koordinate , NULL ) -- z-Koordinate , NULL -- SDO_ELEM_INFO_ARRAY , NULL );-- SDO_ORDINATE_ARRAY ELSE RETURN NULL; END IF; END; SELECT to_sdo(48.16989342,11.55152705 ) AS geom – Unterhaching/München FROM dual;
Na, auf den Geschmack gekommen? Weitere Beispiele erhalten Sie z.B. in unserem PL/SQL Kurs. Besuchen Sie uns doch mal im schönen Unterhaching bei München.