10. Juli 2007

Zusammenführung grosser Default-Where-Bedingungen

Der einfachste Weg um Where-Bedingungen zu konkatinieren ist:

Beispiel: Eine leere Maske mit der Tabelle DEPT. In diesem Beispiel soll es drei Regeln geben, nach denen die Default-Where-Bedingung aufgebaut wird. Das Problem ist: Ab dem zweiten IF muss man jedesmal überprüfen, ob in V_Default_Where schon etwas drinsteht. Falls ja wird ein ' AND ' dran konkatiniert vor jedem neuen Teilstring.

DECLARE
V_Default_Where VARCHAR2 (2000);
BEGIN
IF Rule_1_is_TRUE THEN
V_Default_Where := 'DEPTNO IN (10, 20, 30)';
END IF;

IF Rule_2_is_TRUE THEN
IF V_Default_Where IS NOT NULL THEN
V_Default_Where := V_Default_Where ||
' AND DNAME != ''SALES'' ';
ELSE
V_Default_Where := 'DNAME != ''SALES'' ';
END IF;
END IF;

IF Rule_3_is_TRUE THEN
IF V_Default_Where IS NOT NULL THEN
V_Default_Where := V_Default_Where ||
' AND LOC IS NOT NULL';
ELSE
V_Default_Where := 'LOC IS NOT NULL';
END IF;
END IF;

Set_Block_Property ('DEPT', DEFAULT_WHERE,
V_Default_Where);
Go_Block ('DEPT');
Execute_Query;
END;

Diese IF's sind nicht wartbar. Änderungen in der Where-Bedingung bedeuten immer zwei Änderungen im Code:

...
V_Default_Where := V_Default_Where ||
' AND LOC IS NULL';
ELSE
V_Default_Where := 'LOC IS NULL';
...

Ein besserer Ansatz ist die Benutzung von ' AND ' bei jeder Konkatinierung:

DECLARE
V_Default_Where VARCHAR2 (2000);
BEGIN
IF Rule_1_is_TRUE THEN
V_Default_Where := ' AND DEPTNO IN (10, 20, 30)';
END IF;

IF Rule_2_is_TRUE THEN
V_Default_Where := V_Default_Where ||
' AND DNAME != ''SALES'' ';
END IF;

IF Rule_3_is_TRUE THEN
V_Default_Where := V_Default_Where ||
' AND LOC IS NOT NULL';
END IF;

Set_Block_Property ('DEPT', DEFAULT_WHERE,
Substr (V_Default_Where, 6));
Go_Block ('DEPT');
Execute_Query;
END;


der Substr (V_Default_Where, 6) eliminiert zum Schluss das führende ' AND '.

Sehr einfacher und wartbarer Code!

PS: In den englischen Kommentaren gibt es eine Erklärung dafür, dass ich nicht den Trick mit "1=1" benutze

Keine Kommentare: