Als PDF Downloaden!

Werbung
Tipps & Tricks: Erweiterung der WITH Klausel
Bereich:
SQL
Erstellung:
07/2013 MP
Versionsinfo:
12.1
Letzte Überarbeitung:
07/2013 MP
Erweiterung der WITH Klausel
Oracle hat in der Version 12c die WITH Klausel erweitert, so dass nun auch Funktionen oder Prozeduren
verwendet werden können.
Einschränkungen: Eine Prozedur darf nur innerhalb der Funktion aufgerufen werden.
SQL Developer Version 3.2.20 und SQL Plus Version 11.2.0.x verstehen die Syntax nicht und erzeugen einen
Fehler:
ORA-06550: Zeile 8, Spalte 2:
PLS-00103: Fand das Symbol "BEGIN"
Nur SQL*Plus 12.1.0 beherrscht (derzeit) das Feature.
Vorteile der Funktion in der WITH Klausel:
Sie brauchen kein CREATE PROCEDURE Recht
Teilweise schnellere Verarbeitung
Schauen wir uns Beispiel 1 an (Prozedur und Funktion stehen auf der gleichen Ebene):
Hier wird die Ausgabe auf die Console (Modus TERMINAL) oder den Webserver (Modus HTML) umgelenkt.
WITH
PROCEDURE p(text IN varchar2) IS
p_mode VARCHAR2(20):='TERMINAL'; -- Modi 'TERMINAL' oder 'HTML'
BEGIN
IF p_mode='TERMINAL' THEN
DBMS_OUTPUT.put_line(text);
ELSIF p_mode='HTML' THEN
htp.p(text||'<BR>');
END IF;
END;
FUNCTION f(id IN NUMBER) RETURN NUMBER IS
BEGIN
p(to_char(id));
RETURN id;
END;
SELECT f(object_id) FROM all_objects
WHERE rownum <4
/
Ausgabe:
F(OBJECT_ID)
Muniqsoft GmbH
Schulungszentrum, Grünwalder Weg 13a, 82008 Unterhaching, Tel. 089 / 679090-40
IT-Consulting & Support, Witneystraße 1, 82008 Unterhaching, Tel. 089 / 6228 6789-0
Seite 1 von 4
-----------49
3
28
49
3
28
Beispiel 2: Prozedur ist in die Funktion im Deklarationsteil eingebettet
WITH
FUNCTION f(id IN NUMBER) RETURN NUMBER IS
PROCEDURE p(text IN varchar2) IS
p_mode VARCHAR2(20):='TERMINAL'; -- Modi 'TERMINAL' oder 'HTML'
BEGIN
IF p_mode='TERMINAL' THEN
DBMS_OUTPUT.put_line(text);
ELSIF p_mode='HTML' THEN
htp.p(text||'<BR>');
END IF;
END;
BEGIN
p(to_char(id));
RETURN id;
END;
SELECT f(object_id) FROM all_objects
WHERE rownum <4
/
Im dritten Bespiel schauen wir uns eine Datumsumwandlungsfunktion an, die etwas toleranter ist als die von
Oracle.
Sie können ein beliebiges Trennzeichen aus der Menge /.,\-;#+*= zwischen Tag / Monat und Jahr verwenden. Der
Monatsname kann in Deutsch/Englisch als drei Buchstaben geschrieben werden. Zweistelliges Jahr wird
automatisch (wie die RR Funktion) auf vierstellig erweitert. Sie können das Beispiel natürlich beliebig erweitern,
um z. B. auch die Uhrzeit zu erfassen. Stellen Sie zuerst das gewünschte Ausgabedatumsformat ein:
ALTER SESSION SET nls_date_format='DD.MM.YYYY';
Wir erstellen uns eine Demo (Staging) Tabelle, in der das Datum in einer Varchar2 Spalte steht und in ein Date
Format gewandelt werden soll:
CREATE TABLE scott.dwh_datum_tab (datum VARCHAR2(30));
INSERT INTO scott.dwh_datum_tab VALUES('01.01.01');
INSERT INTO scott.dwh_datum_tab VALUES('01-Mai.99');
INSERT INTO scott.dwh_datum_tab VALUES('30/DeC.2001');
INSERT INTO scott.dwh_datum_tab VALUES('02-jan:1932');
COMMIT;
Muniqsoft GmbH
Schulungszentrum, Grünwalder Weg 13a, 82008 Unterhaching, Tel. 089 / 679090-40
IT-Consulting & Support, Witneystraße 1, 82008 Unterhaching, Tel. 089 / 6228 6789-0
Seite 2 von 4
Nun beginnt unsere Funktion in der WITH Klausel:
WITH FUNCTION to_date2(p_date IN VARCHAR2 ) RETURN DATE IS
v_month VARCHAR2(30);
v_day VARCHAR2(30);
v_year VARCHAR2(30);
v_dummy VARCHAR2(30);
BEGIN
v_dummy:=TRANSLATE(P_DATE,
'/.,\-;#+*=','..........'); -- versch. Trennzeichen in . wandeln
Format zerlegen in drei Teile
v_day:=REGEXP_REPLACE(V_DUMMY,
'([[:digit:]]{1,2}).([[:alnum:]]{1,12}).([[:digit:]]{1,4})','\1');
v_month:=REGEXP_REPLACE(V_DUMMY,
'([[:digit:]]{1,2}).([[:alnum:]]{1,12}).([[:digit:]]{1,4})','\2');
v_year:=REGEXP_REPLACE(V_DUMMY,
'([[:digit:]]{1,2}).([[:alnum:]]{1,12}).([[:digit:]]{1,4})','\3');
-- Monatsnamen ersetzen durch Zahlen (Sie können weitere Sprachen ergänzen)
IF UPPER(v_month) IN ('JAN')
THEN v_month:='01'; END IF;
IF UPPER(v_month) IN ('FEB')
THEN v_month:='02'; END IF;
IF UPPER(v_month) IN ('MAR','MÄR')
THEN v_month:='03'; END IF;
IF UPPER(v_month) IN ('APR')
THEN v_month:='04'; END IF;
IF UPPER(v_month) IN ('MAI','MAY')
THEN v_month:='05'; END IF;
IF UPPER(v_month) IN ('JUN')
THEN v_month:='06'; END IF;
IF UPPER(v_month) IN ('JUL')
THEN v_month:='07'; END IF;
IF UPPER(v_month) IN ('AUG')
THEN v_month:='08'; END IF;
IF UPPER(v_month) IN ('SEP')
THEN v_month:='09'; END IF;
IF UPPER(v_month) IN ('OKT','OCT')
THEN v_month:='10'; END IF;
IF UPPER(v_month) IN ('NOV','NOV')
THEN v_month:='11'; END IF;
IF UPPER(v_month) IN ('DEZ','DEC')
THEN v_month:='12'; END IF
/*Prüfen ob das Jahr im aktuellen Jahrhundert (bis 2050)
oder im letzten Jahrhundert (ab 1951) liegt*/
IF TO_NUMBER(V_YEAR)<=50 THEN
V_YEAR:=SUBSTR(TO_CHAR(SYSDATE,'YYYY'),1,2)||V_YEAR;
ELSE
IF not length(v_year)=4 THEN -- Nur wenn Jahr nicht vierstellig ist, wird ergänzt
Muniqsoft GmbH
Schulungszentrum, Grünwalder Weg 13a, 82008 Unterhaching, Tel. 089 / 679090-40
IT-Consulting & Support, Witneystraße 1, 82008 Unterhaching, Tel. 089 / 6228 6789-0
Seite 3 von 4
V_YEAR:=TO_NUMBER(SUBSTR(TO_CHAR(SYSDATE,'YYYY'),1,2)-1)||V_YEAR;
END IF;
END IF;
RETURN TO_DATE(v_day||'.'||v_month||'.'||v_year,'DD.MM.YYYY');
END;
SELECT to_date2(datum) as datum FROM scott.dwh_datum_tab
/
Ausgabe:
DATUM
---------01.01.2001
01.05.1999
30.12.2001
02.01.1932
Zum Schluss sollte nicht unerwähnt bleiben, dass die neue Funktion auch gefährlich ist. Ein Benutzer mit
CREATE VIEW aber ohne CREATE PROCEDURE Recht kann folgende View erstellen:
CREATE OR REPLACE VIEW dual as
WITH
FUNCTION f(id IN NUMBER) RETURN NUMBER IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
EXECUTE IMMEDIATE 'drop table scott.wichtig';
RETURN 'X';
END;
SELECT f(1) dummy FROM sys.dual
/
Raten Sie mal, was passiert, wenn jemand den folgenden Befehl im Schema der View absetzt:
SELECT * FROM dual;
Richtig, ihre "Wichtig" Tabelle liegt jetzt im Mülleimer ...
Dies ist nur ein kleiner Ausschnitt der Möglichkeiten, die sich mit der WITH Funktion realisieren lassen. Und wie
immer gilt:
Darf´s noch ein bisschen mehr an Informationen zu Oracle 12c sein? Dann besuchen Sie doch unseren Oracle
12c Neuerungen Kurs. Wir freuen uns auf Sie!
Muniqsoft GmbH
Schulungszentrum, Grünwalder Weg 13a, 82008 Unterhaching, Tel. 089 / 679090-40
IT-Consulting & Support, Witneystraße 1, 82008 Unterhaching, Tel. 089 / 6228 6789-0
Seite 4 von 4
Herunterladen