Gelegentlich kommt man in die Verlegenheit, dass eine Prozedur oder Funktion in unterschiedlichen Datenbank-Versionen unterschiedlich heisst, ein Skript mit ihrem Aufruf aber auf möglichst vielen Datenbank-Versionen laufen soll. Hier hilft (vor Version 10.2) nur dynamisches SQL weiter.
In DBMS_UTITLIY gibt es bis Version 9.0.x eine Funktion namens IS_PARALLEL_SERVER. Ab Version 9.2 existiert diese nicht mehr; stattdessen wurde IS_CLUSTER_DATABASE eingeführt. An diesem Beispiel soll hier exemplarisch gezeigt werden, wie so etwas mit EXECUTE IMMEDIATE bzw. DBMS_SQL realisierbar ist. Beide Funktionen sind vom Datentyp BOOLEAN.
Als Returnwerte für dynamisches SQL können nur Server-Datentypen verwendet werden, daher muss der Return-Wert zusätzlich gewandelt werden, am besten zu einer Zahl.
Im folgenden Beispiel wurde der dynamische Aufruf der Funktion der Überschaubarkeit wegen in eine eigenständige Funktion gepackt; in der Praxis, wenn man mit Skripten arbeitet, ist er sinnvollerweise Teil des Skripts.
Beispiel mit EXECUTE IMMEDIATE:
CREATE OR REPLACE FUNCTION IS_PARALLEL(p_version NUMBER) RETURN BOOLEAN IS
v_string VARCHAR2(2000);
v_call VARCHAR2(2000);
v_result INTEGER;
v_ret BOOLEAN;
BEGIN
IF p_version >= 92000 THEN
v_call := 'v_isParallel := DBMS_UTILITY.IS_CLUSTER_DATABASE;';
ELSE
v_call := 'v_isParallel := DBMS_UTILITY.IS_PARALLEL_SERVER;';
END IF;
v_string := 'DECLARE
v_isParallel boolean;
BEGIN
'||v_call||'
:v_ret := SYS.DIUTIL.bool_to_int(v_isParallel);
END;';
EXECUTE IMMEDIATE v_string
USING OUT v_result;
v_ret := SYS.DIUTIL.int_to_bool(v_result);
RETURN v_ret;
END IS_PARALLEL;
/
EXECUTE IMMEDIATE ist seit Version 8i verfügbar; soll die Funktion in noch niedrigeren Versionen eingesetzt werden, so muss stattdessen DBMS_SQL verwendet werden:
Beispiel mit DBMS_SQL:
CREATE OR REPLACE FUNCTION IS_PARALLEL(p_version NUMBER) RETURN BOOLEAN IS
v_string VARCHAR2(2000);
v_call VARCHAR2(2000);
v_cur INTEGER;
v_ret_cur INTEGER;
v_result INTEGER;
v_ret BOOLEAN;
BEGIN
IF p_version >= 92000 THEN
v_call := 'v_isParallel := DBMS_UTILITY.IS_CLUSTER_DATABASE;';
ELSE
v_call := 'v_isParallel := DBMS_UTILITY.IS_PARALLEL_SERVER;';
END IF;
v_string := 'DECLARE
v_isParallel boolean;
BEGIN
'||v_call||'
:v_ret := SYS.DIUTIL.bool_to_int(v_isParallel);
END;';
v_cur := DBMS_SQL.open_cursor;
DBMS_SQL.parse(v_cur, v_string, DBMS_SQL.V7);
DBMS_SQL.bind_variable(v_cur, ':v_ret', v_result);
v_ret_cur := DBMS_SQL.execute(v_cur);
DBMS_SQL.VARIABLE_VALUE(v_cur, ':v_ret', v_result);
DBMS_SQL.CLOSE_CURSOR(v_cur);
v_ret := SYS.DIUTIL.int_to_bool(v_result);
RETURN v_ret;
END IS_PARALLEL;
/
Der Aufruf dieser Funktion würde in etwa so aussehen:
DECLARE
v_version VARCHAR2(2001);
v_comp VARCHAR2(2001);
v_version_number NUMBER;
BEGIN
DBMS_UTILITY.DB_VERSION(v_version, v_comp);
v_version_number := TO_NUMBER(REPLACE(v_version, '.'));
IF IS_PARALLEL(v_version_number) THEN
DBMS_OUTPUT.PUT_LINE('Parallel Server / RAC');
ELSE
DBMS_OUTPUT.PUT_LINE('kein Parallel Server / RAC');
END IF;
END;
/
Anmerkungen:
Niederlassungen
Witneystraße
089 6228 6789-0
Grünwalder Weg
089 679090-40
E-Mail:
Bitte nehmen Sie mich in den Verteiler der monatlichen Tipps & Tricks auf.