Mit einer Prozedur generisch Daten auf verschiedene Seiten verteilen

02.
Februar
2021
Veröffentlicht von: Andreas Mößel

Die APEX APIs für JavaScript und PL/SQL sind vermutlich die am häufigsten genutzten Hilfsmittel bei der Entwicklung von komplexen Anwendungen. Neben diesen gibt es auch die APEX -Views, deren Nutzen sich vielleicht nicht auf den ersten Blick erschließt, aber mit ein wenig Kreativität lassen sich ein paar sehr sinnvolle Verwendung finden.

Übersicht über die Views

Es gibt in etwa 75 verschiedene Views für APEX, auf die man durch öffentliche Synonyme zugreifen kann. Viele dieser Views, wie APEX_WORKSPACE_ACTIVITY_LOG oder APEX_WORKSPACE_CLICKS, sind hervorragend dazu geeignet sich eigene Dashboards zu bauen, mit denen man die Verwendung und das Wachstum der Applikationen im Workspace im Auge behalten kann.

Ein anderes Beispiel ist das öffentliche Synonym APEX_COLLECTIONS, welches auf das Package WWV_APEX_COLLECTIONS zeigt, das in Kombination mit dem gleichnamigen Paket dazu verwendet wird, Daten temporär für die Session zu speichern und wieder abzurufen.

Oder, wie im Folgendem gezeigt, die View APEX_APPLICATION_PAGE_ITEMS, mit der Items auf verschiedenen Seiten generisch gefüllt werden können.
 

APEX_APPLICATION_PAGE_ITEMS

Die View APEX_APPLICATION_PAGE_ITEMS enthält Informationen zu Applikationsnummer, Applikationsnamen, Seitennummer, Seitennamen, Regionsnamen und Workspace unter welchen das Item verwendet wird. Sowie Informationen zu den Einstellungen des Templates, ob es einen Default-Wert gibt oder welche LoV (List of Value) es verwendet.

Über die Zuordnung von Applikationsnummer und Seitennummer lässt sich das Item leicht finden, wenn nach Items auf einer bestimmten Seite gesucht wird.

Aufgabenstellung

Angenommen es gibt eine Art von Datensatz, der häufig auf verschiedenen Seiten in unterschiedlichen Applikationen gebraucht wird, aber jede Seite benötigt eine andere Teilmenge dieses Datensatzes.

Die direkte Lösung ist es, eine Prozedur zu schreiben, die den gewünschten Datensatz holt und zusätzlich für jede Seite eine eigene Prozedur anzulegen, die angepasst auf das Bedürfnis der Seite den Datensatz in die Items füllt.

Die Alternative ist, nur eine Prozedur zu implementieren, die die Daten abholt und anhand der Parameter die gewünschten Daten auf allen Seiten in die richtigen Items verteilen kann.

Umsetzung

Die Idee hinter dieser Prozedur in Kombination mit der View APEX_APPLICATION_PAGE_ITEMS ist relativ einfach:

  • Es wird der Datensatz aus der Tabelle geholt und in einen Record gespeichert
  • Anhand der übergebenen Parameter der Prozedur werden die passenden Item-Namen aus der View APEX_APPLICATION_PAGE_ITEMS ausgelesen
  • Über eine CASE-Anweisung in einer Schleife wird anhand des Namens geprüft, ob er einen Wert aus dem Datensatz aufnehmen darf

Es gibt allerdings eine Voraussetzung damit diese Idee funktioniert: Die Namen der Items müssen einem festgelegten Schema folgen, sodass die Werte eindeutig den Items zugeordnet werden können.

Codebeispiel

In meinem Beispiel wird der angeforderte Datensatz in folgendem Record gespeichert:

TYPE t_data_rec IS RECORD(
  data_name           VARCHAR2,
  data_id             NUMBER,
  data1               VARCHAR2,
  data2               VARCHAR2,
  data3               VARCHAR2
);


Der gefüllte Record wird zusammen mit der Applikationsnummer und der Seitennummer an die Verteilungs-Prozedur gegeben. Die Prozedur sucht sich dann mit Hilfe der beiden Nummern alle auf der Seite befindlichen Item-Namen heraus und gleicht diese mit einer Liste von Namenskonventionen ab. Wenn der Item-Name mit einem Eintrag aus der CASE-Anweisung übereinstimmt, wird das Item mit dem entsprechenden Wert aus dem Record belegt.

PROCEDURE fill_data_into_items ( p_application IN NUMBER,
                                 p_page IN NUMBER,
                                 p_data IN t_data_rec)
IS
  v_itemname_tab IS TABLE OF apex_application_page_items.item_name%TYPE;

BEGIN
  SELECT iten_name INTO v_itemname_tab
  FROM apex_application_page_items
  WHERE application_id = p_application
    AND page_id = p_page;

  FOR i IN 1 .. v_itemname_tab.count LOOP
    CASE v_itemname_tab(i)
      WHEN 'P'||p_page||'_DATA_NAME'
        THEN APEX_UTIL.SET_SESSION_STATE(v_itemname_tab(i), p_data.data_name);
      WHEN 'P'||p_page||'_DATA_ID'
        THEN APEX_UTIL.SET_SESSION_STATE(v_itemname_tab(i), p_data.data_id);
      WHEN 'P'||p_page||'_DATA1'
        THEN APEX_UTIL.SET_SESSION_STATE(v_itemname_tab(i), p_data.data1);
      WHEN 'P'||p_page||'_DATA2'
        THEN APEX_UTIL.SET_SESSION_STATE(v_itemname_tab(i), p_data.data2);
      WHEN 'P'||p_page||'_DATA3'
        THEN APEX_UTIL.SET_SESSION_STATE(v_itemname_tab(i), p_data.data3);
      ELSE NULL;
    END CASE;
  END LOOP;
END;

Am Ende dieser Prozedur steht für jedes gültige Item auf der Seite ein Wert aus dem angeforderten Datensatz im Session State und kann durch einen Refresh des Items, der Region oder der Seite angezeigt werden.

Da sich nur auf bestimmte Regionen und Items ein Refresh durchführen lässt, kann man auch die ganze Seite neu laden. Das lässt sich entweder durch ein Submit oder Redirect auf die gleiche Wunschseite bewerkstelligen oder man implementiert ein Dynamic Action, welches folgendes JavaScript ausführt und die Seite neu lädt:

Location.Reload();

Zusammenfassung

Man braucht also nicht für jede Seite eine eigene Prozedur, die alle denselben Datensatz auf ihre Items verteilen. Unter Hilfenahme der APEX_APPLICATION_PAGE_ITEMS-View und einer CASE-Anweisung in einer Schleife kann man diese seitenspezifischen Prozeduren auf eine einzige generische Prozedur vereinfachen, was die eigenen Applikationen im Punkt Wartung und Wiederverwendbarkeit sichtbar weiterbringt.

Jede Menge Know-how für Sie!

In unserer Know-How Datenbank finden Sie mehr als 300 ausführliche Beiträge zu den Oracle-Themen wie DBA, SQL, PL/SQL, APEX und vielem mehr.
Hier erhalten Sie Antworten auf Ihre Fragen.