Oracle APEX Audit Plug-In Download

Dieses PlugIn ist im Rahmen meines Buches “Oracle Application Express in der Praxis: Mit APEX Datenbankbasierte Webanwendungen entwickeln”, welches vom Hanser Verlag verlegt wurde, entstanden. Die damalige Version des Processs-Plug-In basierte auf APEX 4.2 und kann hier herunter geladen werden.

APEX Audit PlugIn

APEX Plug/In , welches automatisch die Änderungen , die über ein Formular erfasst werden, protokolliert.

Autor: Ralf Beckmann
Lizenz: MIT

Oracle-Datenbank: Teamwork mit Bordmitteln

Synchronisieren Sie mit DDL-Triggern gemeinsames Arbeiten durch Ein -und Ausschenken von Objekten. Und das sogar für beliebige Datenbanktools.

Viele namhafte Tools zur Datenbankentwicklung bieten Funktionen zur Unterstützung von Entwicklerteams. So können Sie Datenbankobjekte zur Bearbeitung ausschenken. Andere Entwickler, können solange keine Änderungen an diesem Objekt mehr vornehmen, bis dieses wieder eingecheckt wurde. Leider funktioniert das meist nicht werkzeugübergreifend, da diese Tools oft eigene Tabellen für die Verwaltung der Bearbeitungszustände der Datenbankobjekte nutzen.

In diesen Beitrag möchte ich Ihnen eine einfache, aber effektive Möglichkeit zeigen, wie Sie so eine Funktion mit Bordmitteln der Oracle Datenbank selber entwickeln können. Vor allem ist bei der vorgestellten Lösung beachtenswert, dass Sie werkzeugübergreifend funktioniert.

Datenmodell

Benötigt werden zwei Tabellen. Über die Tabelle ddl_object_state wird der Bearbeitungsstand der Datenbankobjekte verwaltet. Sobald ein Entwickler ein Objekt bearbeiten möchten, blockt er dieses. Dabei wird ein Datensatz in dieser Tabelle eingefügt. Ist die Bearbeitung abgeschlossen, so wird das Objekt wieder freigegeben und der zugehörige Einträge entfernt.


CREATE TABLE ddl_object_state (
          object_type VARCHAR2(50 BYTE),
          object_owner VARCHAR2(32 BYTE),
          object_name VARCHAR2(32 BYTE), 
          changed_on DATE,
          changed_by VARCHAR2(32 BYTE)
)
/

Listing 1: Tabelle ddl_object_state

In der zweiten Tabelle ddl_object_state_hist wird beim Ein- und Auschecken neben den Statusinformationen auch ein DDL-Extrakt des bearbeiteten Objektes eingetragen. So dass Sie auf einen Stand zu Beginn und zum Ende der Bearbeitung zurückgreifen können.


CREATE TABLE ddl_object_state_hist
(
   object_type VARCHAR2 (50 BYTE),
   object_owner VARCHAR2 (32 BYTE),
   object_name VARCHAR2 (32 BYTE),
   status_code VARCHAR2 (20 BYTE),
   changed_on DATE,
   changed_by VARCHAR2 (32 BYTE),
   ddl_sql CLOB
)
/

Listing 2: Tabelle ddl_object_state_hist

PL/SQL Package ddl_util

Das PL/SQL Package fasst die benötigten Prozeduren zusammen.

PROCEDURE lock_object (
     p_object_type VARCHAR2,
     p_owner VARCHAR2,
     p_name VARCHAR2,
     p_trace_hist BOOLEAN DEFAULT true
  ) IS
    l_c NUMBER;
    l_locked_by VARCHAR2(32);
    l_changed_on DATE;
    l_ddl_extract CLOB;
BEGIN
    SELECT
      COUNT(*)
     INTO l_c
    FROM ddl_object_state
    WHERE object_owner = p_owner
       AND object_name = p_name;

  IF l_c = 0 THEN
       INSERT INTO ddl_object_state (
          object_type,
          object_owner,
          object_name,
          changed_on,
          changed_by )
       SELECT
          p_object_type,
          p_owner object_owner,
          p_name object_name,
          SYSDATE changed_on,
          ora_login_user changed_by
       FROM dual;

    IF p_trace_hist THEN
       l_ddl_extract := dbms_metadata.get_ddl(p_object_type,p_name);

       INSERT INTO ddl_object_state_hist (
          object_type,
          object_owner,
          object_name,
          ddl_sql,
          status_code,
          changed_on,
          changed_by )
       SELECT
          p_object_type,
          p_owner object_owner,
          p_name object_name,
          l_ddl_extract,
          'LOCK',
          SYSDATE changed_on,
          ora_login_user changed_by
       FROM dual;
    END IF;
 ELSE
      SELECT
          changed_by,
          changed_on
      INTO
        l_locked_by,
        l_changed_on
      FROM ddl_object_state
      WHERE object_owner = p_owner
        AND object_name = p_name;

     IF l_locked_by <> ora_login_user THEN
        raise_application_error(-20001,'Object was already locked by '
             || l_locked_by
             || ' at '
             || TO_CHAR(l_changed_on,'dd.mm.yyyy HH24:Mi:ss') );
     END IF;
 END IF;

END;

Listing 3: Procedure lock_object

Die Prozedur lock_object erhält als Parameter beim Aufruf den Objekttyp, den Besitzer des Objektes und den Namen des Objektes.

Als erstes prüft die Prozedur, ob das Objekt bereits von einem anderen User ausgescheckt wurde. Ist das der Fall wird ein application_error -20001 ausgelöst. Wenn das Objekt nicht in Bearbeitung ist, trägt die Prozedur diese in der Tabelle ddl_object_state ein und extrahiert eine DDL-Anweisung des Objektes. Diese wird dann in der Tabelle ddl_object_state archiviert.

PROCEDURE unlock_object (
     p_object_type VARCHAR2,
     p_owner VARCHAR2,
     p_name VARCHAR2,
     p_trace_hist BOOLEAN DEFAULT true,
     p_secure_mode BOOLEAN DEFAULT true) 
IS
     l_c NUMBER;
     l_locked_by VARCHAR2(32);
     l_changed_on DATE;
     l_ddl_extract CLOB;
BEGIN
     SELECT COUNT(*)
       INTO l_c
     FROM ddl_object_state
     WHERE object_owner = p_owner
       AND object_name = p_name;

 IF l_c = 1 THEN
     SELECT
       changed_by,
       changed_on
     INTO
       l_locked_by,
       l_changed_on
     FROM ddl_object_state
     WHERE object_owner = p_owner
       AND object_name = p_name;

    IF p_secure_mode AND l_locked_by <> ora_login_user  THEN
        raise_application_error(-20002,'You have no permissions in secure mode to unlock the object. The Object was locked by '
              || l_locked_by
              || ' at '
              || TO_CHAR(l_changed_on,'dd.mm.yyyy HH24:Mi:ss') );
    END IF;

    DELETE ddl_object_state
      WHERE object_owner = p_owner
        AND object_name = p_name;

    IF p_trace_hist THEN
      l_ddl_extract := dbms_metadata.get_ddl(p_object_type,p_name);

      INSERT INTO ddl_object_state_hist (
            object_type,
            object_owner,
            object_name,
            ddl_sql,
            status_code,
            changed_on,
            changed_by )
      SELECT
            p_object_type,
            p_owner object_owner,
            p_name object_name,
            l_ddl_extract,
            'UNLOCK',
            SYSDATE changed_on,
            ora_login_user changed_by
      FROM dual;
   END IF;
 
 END IF;

END;

Listing 4: Procedure unlock_object

Um ein Datenbankobjekt nach der Bearbeitung wieder frei zu geben, nutzen Sie die Prozedur unlock_object. Diese prüft im Secure Mode, ob Sie im Vorfeld das entsprechende Objekt auch selber ausgelockt haben. Ist das nicht der Fall, wird der Applikationsfehler -20002 ausgelöst. Ein von Ihnen ausgelocktes Objekt wird durch das Löschen des zugehörigen Eintrags in der Tabelle ddl_object_state wieder zur Bearbeitung frei gegeben. In der Tabelle ddl_object_state_hist wird wieder ein DDL-Extrakt gespeichert.

Objekte, die von einem anderen Entwickler als Sie selbst geblockt wurden, können Sie durch das Setzen des Parameters p_secure_mode = false wieder freigegeben. Auch dabei wird ein Historiendatensatz erzeugt. Anschließend können Sie so den Besitz durch Aufrufen von lock_object übernehmen.

PROCEDURE check_object_state (
             p_object_type VARCHAR2,
             p_owner VARCHAR2,
             p_name VARCHAR2
           );

Listing 5: Procedure check_object_state

Mit der dritten Procedur check_object_state können Sie einfach den Bearbeitungsstand eine Datenbankobjektes überprüfen.

Wie bereits erwähnt, speichern die Prozeduren beim Ein- und Auschecken jeweils ein DDL-Statements in der Historientabelle. Wenn Sie eine genaue Protokollierung aller Anpassungen benötigen, möchte ich Sie auf den Artikel Oracle Datenbankentwicklung: DDL-Trigger zur Auditierung von Strukturänderungen hinweisen.

DDL-Trigger

Anschließend benötigen Sie noch zwei DDL-Trigger, die Sie in dem Entwicklungsschema anlegen müssen.


CREATE OR REPLACE TRIGGER trg_ddl_util_before 
     BEFORE ALTER OR DROP 
    ON DATABASE 
DECLARE 
BEGIN
      IF ora_dict_obj_name NOT IN (
               'TRG_DDL_UTIL_BEFORE',
               'TRG_DDL_UTIL_AFTER',
               'DDL_UTIL' ) 
          AND ora_login_user NOT IN (
               'SYS',
               'SYSTEM' ) 
      THEN
         ddl_util.lock_object(ora_dict_obj_type,ora_dict_obj_owner,ora_dict_obj_name);
      END IF;
END;
/

Listing 6: Trigger trg_ddl_util_before

Der Trigger trg_ddl_util_before wird bei ALTER- und DROP-Anweisungen ausgeführt. Für einen Create-Befehl macht dieser Zeitpunkt keinen Sinn, da das Objekt in der Datenbank noch nicht vorliegen kann.

Bei der Verwendung von DDL-Triggern sollten Sie besondere Vorsicht walten lassen. Da diese Trigger auch bei Änderungen an sich selbst gefeuert werden, kann es vorkommen, dass man bei einer fehlerhaften Programmierung evtl. keine Änderungen mehr an den Triggern vornehmen kann. Aus diesem Grund prüft der Trigger zu Beginn, ob Änderungen an ihm selbst bzw. an dem Trigger trg_ddl_util_after ausgeführt werden sollen. Des Weiteren werden die Accounts das und system von der Verarbeitung ausgenommen. Allerdings würde auch ein invaliden Package ddl_util zu Problemen führen können.

Die eigentlich Logik des Triggers besteht dann nur noch im Aufruf der Prozedur ddl_util.lock_object. Diese prüft, ob das Objekt von einem anderen Entwickler zur Bearbeitung ausgescheckt wurde. In diesem Fall wird wie bereits erwähnt eine Exception gefeuert und so die Änderungen an dem Objekt dem aktuellen Nutzer verwährt. Bei Objekten, die noch nicht ausgescheckt sind, wird das über diesen Trigger automatisch erledigt.

Alternativ kann es aber auch durchaus sinnvoll sein, dass Ausschecken eines Objektes vor der Bearbeitung manuell durch das Aufrufen von  ddl_util.lock_object durchzuführen. So erspart man sich, dass Änderungen beim Speichern durch den Trigger erst im Nachhinein verworfen werden.

CREATE OR REPLACE TRIGGER trg_ddl_util_after 
    AFTER CREATE OR DROP 
 ON DATABASE 
DECLARE 
BEGIN
    IF ora_dict_obj_name NOT IN (
              'TRG_DDL_UTIL_BEFORE',
              'TRG_DDL_UTIL_AFTER',
              'DDL_UTIL')
    AND ora_login_user NOT IN (
              'SYS',
              'SYSTEM' )
    THEN
        IF ora_sysevent = 'CREATE' THEN
            ddl_util.lock_object(ora_dict_obj_type,ora_dict_obj_owner,ora_dict_obj_name);
       END IF;

       IF ora_sysevent = 'DROP' THEN
           ddl_util.unlock_object(ora_dict_obj_type,ora_dict_obj_owner,ora_dict_obj_name,false,true);
       END IF;

    END IF;
END;
/

Listing 7: Trigger trg_ddl_util_after

Wird nun ein neues Objekt angelegt, kann dieses nicht im Vorfeld geblockt werden. In so einem Fall kommt nun der zweite Trigger trg_ddl_util_after ins Spiel. Dieser prüft ob ein Create-Statement ausgeführt wurde. Wenn das der Fall war, wird das neu erstellte Datenbankobjekt automatisch ausgecheckt und der DDL-Extrakt archiviert.

Bei einem Drop-Befehl verhält es sich etwas anders. Hier existiert das Objekt zum Ausführungszeitpunkt ( AFTER ) des Triggers nicht mehr. Es muss aber noch aus der Tabelle ddl_objet_state entfernt werden.

Abbildung 1: Übersicht ddl_util

In Abbildung 1 sehen Sie alle beschriebenen Objekte.

Drop …

Jetzt habe ich der Einfachheit halber Ihnen noch ein kurzes Skript hier eingefügt, mit dem Sie die Tabellen, Trigger und das Package wieder los werden können.


DROP TRIGGER trg_ddl_util_before;
DROP TRIGGER trg_ddl_util_after;
DROP PACKAGE ddl_util;
DROP TABLE ddl_object_state;
DROP TABLE ddl_object_state_hist;

Beispiel

Im Folgenden möchte ich Ihnen die Nutzung der beschrieben Methode anhand einiger kleiner Beispiele demonstrieren. Dazu wurden in dem Schema MY_PROJECTS die beiden Tabellen, das Package und die beiden Trigger angelegt. diesen Account wurde eine Verbindung im SQL Developer hergestellt.

Dann gibt es einen weiteren Account namens DEVELOPER1, welcher mit DBA-Rechten versehen wurde. Der DEVELOPER1  ist via. sqlplus mit der Datenbank verbunden.

Tabelle T1 anlegen

Zu Beginn soll eine Tabelle erzeugt werden.

Abbildung 2: Tabelle T1 anlegen

Wie Sie der Abbildung 2 entnehmen können, wurde die Tabelle T1 ohne Probleme erzeugt. Dabei wurde der Trigger trg_ddl_util_after ausgeführt und ein Lock-Eintrag in der Tabelle ddl_object_state eingefügt.

Abbildung 3: Datenbanktabelle T1 für ausgecheckt

Tabelle T2 erweitern

Jetzt soll der DEVELOPER1 dieser Tabelle eine neue Spalte hinzufügen.

Abbildung 4 : Spalte in T1 ergänzen

Wie zu erwarten war, wird dieser Vorgang mit der Exception ORA-20001 durch den Trigger trg_ddl_util_before unterbunden. Der Meldung können Sie entnehmen, dass die Tabelle durch den User MY_PROJECTS am 17.06.2018 um 20:59:17 gesperrt wurde.

Abbildung 5: Objekt einchecken

Erst wenn der Benutzer MY_PROJECTS die Tabelle wieder zur Bearbeitung frei gibt, kann der DEVELOPER1 die Spalte ergänzen.

Abbildung 6: Spalte hinzufügen

Dies hat wiederum zu Folge, dass die Tabelle jetzt durch den User DEVELOPER1 ausgecheckt wurde.

Tabelle T1 löschen

Setzt nun der User MY_PROJECTS eine Drop Anweisung für die Tabelle T1 ab, wird auch diese mit einer entsprechenden Fehlermeldung abgebrochen.

Abbildung 7: Drop der Tabelle nicht möglich

Möchten Sie jetzt aber die Tabelle trotzdem löschen und die Sperre durch den DEVELOPER1 übergehen, so können Sie das durch den Aufruf der Prozedur unlock_objects mit folgenden Parametern tun.


BEGIN
  DDL_UTIL.UNLOCK_OBJECT(
         P_OBJECT_TYPE = 'TABLE',
         P_OWNER =       'MY_PROJECTS',
         P_NAME =        'T1',
         P_TRACE_HIST =  true,
         P_SECURE_MODE = false
        );
   commit;
END;

Änderungshistorie

Die Trigger bzw. das PL/SQL Package ddl_util sorgen beim Ein- und Auschecken der Datenbankobjekte auch dafür, dass ein DDL-Extrakt in der Tabelle ddl_object_state_hist archiviert wird. So können Sie auf einfache Weise auf ältere Entwicklungsstände zugreifen.

Abbildung 8: Änderungshistorie

Download

Abschließend habe ich Ihnen ein DDL-Script zum Anlegen der beschriebenen Objekte an diesen Beitrag angefügt. Die Verwendung erfolgt aber auf eigene Gefahr.

Oracle-Datenbank: Teamwork mit Bordmitteln Download ddl_util.sql

Dieses DDL-Sript ist im Rahmen des Beitrags Oracle-Datenbank: Teamwork mit Boardmitteln entstanden.

Oracle Datenbankentwicklung: DDL-Trigger zur Auditierung von Strukturänderungen

Oracle bietet mit sogenannten DDL-Triggern eine einfache Möglichkeit Änderungen an Datenbankobjekten zu protokollieren. Eine nützliche Methode für Entwicklerteams.

Eine automatische Auditierung von DDL (Data Definition Language) -Aktionen in einem Datenbank-Schema ist in vielerlei Situationen nützlich. Z.B. können Sie auf diese Weise in einer Entwicklungsumgebung alle Strukturänderungen, die nach einem bestimmten Zeitpunkt erfolgt sind, nachvollziehen. Auf Basis so eines Protokolls sind Sie dann beispielsweise in der Lage ein Upgrade-Skript zu erstellen, mit dem Sie anschließend das produktive System aktualisieren können. Auch aus Sicherheitsgründen kann es sinnvoll sein, strukturelle Änderungen an einer Datenbank zu protokollieren.

Das Thema der DDL- oder auch Systemtrigger ist umpfangreich, soll hier aber nicht in Gänze betrachtet werden. In diesem Beitrag geht es um die Entwicklung  eines Auditierungsmechanismusses, der alle Änderungen an einem Schema protokolliert. Das sind vor allem create, alter, drop Befehle.

Eine Oracle-Datenbank bietet verschiedene Möglichkeiten der Auditierung. Die hier vorgestellte Variante ist aber recht leichtgewichtig und bietet durch ihre Anpassbarkeit viele Gestaltungsmöglichkeiten. So können Sie beispielsweise auch eine DSGVO angepasste, datensparsame  Variante erstellen.

Die dargestellten Beispiele sind mit viel Sorgfalt entstanden, allerdings übernehme ich keine Gewähr für etwaige Fehler oder Probleme, die bei der Nutzung auftreten. Bitte prüfen Sie selber die Beispiele vor der Nutzung.

Datenmodell

Das Datenmodell für dieses Szenario besteht aus zwei Tabellen.

Die Tabelle ddl_log nimmt für jede Änderung der Datenbankobjekte deren Name und Besitzer, den Typ des Objektes, den Zeitpunkt der Änderung und die Art der Änderung auf. Auch die Benutzerdaten sowie das Programm, mit dem die Änderung durchgeführt wurde, werden vermerkt. Zur Erzeugung eines künstlicher Schlüssel wird später eine Sequence verwendet.

Die zweite Tabelle ddl_log_sql ergänzt diese Information um das eigentliche DDL-Statement, welches  ausgeführt wurde.

CREATE TABLE ddl_log
(
  event_id NUMBER (10, 0),
  event_date DATE,
  user_id VARCHAR2 (30 BYTE),
  object_name VARCHAR2 (30 BYTE),
  owner VARCHAR2 (30 BYTE),
  object_type VARCHAR2 (30 BYTE),
  system_event VARCHAR2 (30 BYTE),
  machine VARCHAR2 (64 BYTE),
  program VARCHAR2 (64 BYTE)
)
/

CREATE TABLE ddl_log_sql
(
  event_id NUMBER (10, 0),
  sqlline NUMBER (10, 0),
  sqltext VARCHAR2 (4000 BYTE)
)
/

CREATE SEQUENCE ddl_log_id INCREMENT BY 1
  START WITH 1
  MINVALUE 1
  MAXVALUE 9999999999999999999999999999
  NOCYCLE
  ORDER
  CACHE 20
/

Listing 1: Datenmodell anlegen

Mit Listing 1 können Sie die beschriebenen Objekte anlegen. Dies sollten Sie in dem Schema tun, in dem Sie die Änderungen protokollieren möchten. Alternativ können Sie aber auch ein eigenes Schema dafür definieren. Allerdings müssen Sie dann den Schema-Namen im Quellcode des Triggers ergänzen und denn Tabellen sowie der Sequence voranstellen.

DDL-Trigger

Ein DDL-Trigger wird anders als ein DML-Trigger bei DDL- bzw. Systemereignissen ausgeführt. Das können z.B. Strukturänderungen wie das Erstellen einer Tabelle oder eines PL/SQL Packages, das Droppen einer Tabelle oder das Anlegen einer View aber auch das Anmelden eines Benutzers sein.

Der Ausführungspunkt so eines Triggers kann vor (BEFORE) oder nach (AFTER) der Abarbeitung des DDL-Statements festgelegt werden.

Sie können einen DDL-Trigger global für die komplette Datenbank (DATABASE) oder nur für ein bestimmtes SCHEMA definieren.

Einen DDL-Trigger, der alle Strukturellen Änderungen an Ihrem Schema protokolliert, können Sie – wie in Listing 2 gezeigt – erzeugen. Führen Sie dazu das Skript mit einem Datenbanktool (sqlplus, SQL Developer, APEX SQL Workshop,…) aus. Melden Sie sich dabei mit dem SCHEMA Account an.

Tauschen Sie das keyword SCHEMA durch DATABASE, so wird der Trigger bei allen Änderungen an der gesamten Datenbank gefeuert. Aber Achtung, Sie müssen dafür dann das Schema, in denen sich die verwendeten Tabellen befinden, in dem Trigger hinzufügen.


CREATE OR REPLACE TRIGGER trg_ddl_log
 AFTER DDL
 ON SCHEMA
DECLARE
  l_sql ora_name_list_t;
  l_id NUMBER (10, 0);
BEGIN
  SELECT ddl_log_id.NEXTVAL INTO l_id FROM DUAL;

  INSERT INTO ddl_log (event_id,
    event_date,
    user_id,
    object_name,
    owner,
    object_type,
    system_event,
    machine,
    program)
  (SELECT l_id,
          SYSDATE,
          ora_login_user,
          ora_dict_obj_name,
          ora_dict_obj_owner,
          ora_dict_obj_type,
          ora_sysevent,
          UPPER (SYS_CONTEXT ('USERENV', 'TERMINAL')),
          SYS_CONTEXT ('USERENV', 'MODULE')
       FROM DUAL);

FOR l IN 1 .. ora_sql_txt (l_sql)
  LOOP
    INSERT INTO ddl_log_sql (event_id, sqlline, sqltext)
      VALUES (l_id, l, l_sql (l));
  END LOOP;
END;
/

Listing 2: Create DDL-Audit-Trigger

Der Trigger wird nach allen Änderungen, die an Objekten des jeweiligen Schemas ausgeführt werden, gefeuert.

Zu Begin des Triggers wird mit Hilfe der Sequence ddl_log_id ein künstlicher Schlüssel erzeugt und in der Variable l_id gespeichert.

Das erste Insert-Statement protokolliert die Art der Änderung in der Tabelle ddl_log. Dabei wird dem Datensatz die zuerst erzeugte ID aus der Variablen l_id als Primärschlüssel zugeordnet. Hier werden neben dem Zeitpunkt der Änderung und das geänderte Datenbankobjekt, auch die Benutzerdaten und das verwendete Programm ermittelt und gespeichert.

Im nächsten Schritt wird das DDL-Statement, welches zur Ausführung des Triggers geführt hat, zeilenweise in der Tabelle ddl_log_sql eingefügt. Jeder Zeile wird neben einer Nummerierung auch die l_id als Fremdschlüssel zugeordnet.

Sollten Sie auf die persohnenpersonen Daten – wie den Benutzername und den Maschinennamen des Clients – verzichten wollen, können Sie den Trigger in einer DSGVO freundlicheren Version mit dem Listing 3 anlegen. Dabei werden diese beiden Spalten einfach mit null vorbelegt.


CREATE OR REPLACE TRIGGER trg_ddl_log
 AFTER DDL
 ON SCHEMA
DECLARE
  l_sql ora_name_list_t;
  l_id NUMBER (10, 0);
BEGIN
  SELECT ddl_log_id.NEXTVAL INTO l_id FROM DUAL;

  INSERT INTO ddl_log (event_id,
    event_date,
    user_id,
    object_name,
    owner,
    object_type,
    system_event,
    machine,
    program)
  (SELECT l_id,
          SYSDATE,
          null,
          ora_dict_obj_name,
          ora_dict_obj_owner,
          ora_dict_obj_type,
          ora_sysevent,
          null,
          SYS_CONTEXT ('USERENV', 'MODULE')
       FROM DUAL);

FOR l IN 1 .. ora_sql_txt (l_sql)
  LOOP
    INSERT INTO ddl_log_sql (event_id, sqlline, sqltext)
      VALUES (l_id, l, l_sql (l));
  END LOOP;
END;
/

Listing 3: DSGVO freundlicherer DDL-Audit-Trigger

Möchten Sie den Trigger inklusive der zugehörigen Datenbankobjekte aus Ihrem Schema entfernen, können Sie dafür das Listing 4 nutzen. Wichtig dabei ist die vorgegebene Ausführungsreihenfolge. Würden Sie die Tabellen zuerst zu droppen, so würden Sie dem DDL-Trigger seine abhängigen Objekte entziehen. Anschließend würde der Trigger invalid und zu einem Fehler führen.


DROP TRIGGER trg_ddl_log;
DROP TABLE ddl_log;
DROP TABLE ddl_log_sql;
DROP SEQUENCE ddl_log_id;

Listing 4: Trigger und Tabellen löschen

Generell sollten Sie bei der Verwendung von DDL-Triggern etwas Vorsicht walten lassen, da Sie bei fehlerhafter Verwendung, sich quasi bestimmter Datenbank-Funktionalitäten entledigen könnten.

Anwendungsbeispiele

Ich habe in dem Beitrag Oracle Application Express – Quick SQL bespielhaft ein einfaches Datenmodell für eine Projektverwaltung erstellt. Das zugehörige DDL-Skript habe ich exemplarisch ausgeführt und mit Hilfe des DDL-Audit-Triggers aus Listing 3 protokollieren lassen.

Im Folgenden finden Sie einige einfachen select-Anweisungen, mit deren Hilfe Sie verschiedene Fragestellungen beantworten können.

Wie Sie der Abbildung 1 entnehmen können, wurden folgende Änderungen an der Datenbank vorgenommen.

Abbildung 1: DDL-Log Änderungshistorie

Wenn Sie sich dieses Log ansehen möchten, genügt folgende select-Statement Anweisung:


select event_id,
       event_date,
       user_id,
       object_name,
       owner,
       object_type,
       system_event,
       machine,
       program
 from ddl_log
  order by event_id

Listing 5: Änderungshistorie anzeigen

Das konkrete DDL-Statement, dass für Anlegen der Tabelle projects verantwortlich war,  wurde in der Tabelle ddl_log_sql protokolliert. Eine kleine Unschönheit bringt dieses Protokoll mit sich. Bitte achten Sie darauf, dass die zeilenweise Speicherung teilweise mitten in einer SQL-Anweisung die Zeile umbricht. Dies muss bei der Rekonstruktion des Skriptes beseitigt werden.

Abbildung 2: DDL-Statement

Dieses läßt sich für einen einzelnen Schritt – wie in Listing 6 gezeigt – ermitteln.


select event_id, 
       event_date, 
       object_type,
       sqltext
from ddl_log_sql 
  where event_id = 2
 order by sqlline

Listing 6: DDL-Anweisungen für event_id =2 ermitteln

Interessieren Sie sich für die Änderungen,  die zwischen zwei Releaseständen Ihres Datenbank-Schemas  durchgeführt wurden, können Sie die select-Anweisungen um folgende where Klausel ergänzen. Alternativ können Sie auch die Einschränkungen über den Zeitstempel vornehmen.


select l.event_id, 
       event_date, 
       object_type,
       sqltext
from ddl_log l, 
     ddl_log_sql s
where l.event_id = s.event_id
  and l.event_id > 2 and l.event_id < 10
order by l.event_id, 
         sqlline

Listing 7: Alle DDL-Anweisungen die nach event_id 2 bis zur event_id 5 ausgeführt wurden

Auf Basis so eines Protokolls, können Sie anschließend ein Upgrade-Skript erarbeiten oder die Release-Notes für die neue Softwareversion ergänzen.

Auch die Änderungen an einem bestimmten Datenbankobjekt, hier der Tabelle TO_DOS, können nachvollzogen werden. Dazu finden Sie in Listing 8 ein einfaches Beispiel.


select l.event_id , 
       l.object_name, 
       event_date, 
       object_type,  
       sqltext
from ddl_log l, 
     ddl_log_sql s
where l.event_id = s.event_id
  and l.object_name = 'TO_DOS'
order by l.event_id, 
         sqlline

Listing 8: DDL-Statement zum Erstellen der Tabelle TO_DOS ermitteln

So einen DDL-Audit-Trigger ist gerade auch für Entwicklerteams hilfreich. Hier ist für alle Programmierer leicht nachvollziehbar, welche Änderungen an dem Datenmodell durchgeführt wurden. Auch zum prüfen von Installationsvorgängen lässt sich die Protokollierung einsetzen.

Wie Sie meine ScreenShots entnehmen konnten, setzte ich diesen Trigger auch gerne bei der Entwicklung von APEX-Anwendungen ein. Gerade durch die Beschränkung seiner Ausführung auf die Änderungen eines Datenbankschemas können so geziehlt alle Entwicklungsschritte auf Datenbankebene nachvollzogen werden. Auf Basis der Tabelle ddl_log_sql lassen sich dann Scripte für die Supported Objects erstellen.

 

 

 

 

Oracle Application Express (APEX) 18.1.0.00.45 Download bereitgestellt

Oracle hat die Version 18.1 seiner Entwicklungsumgebung APEX zum Download bereitgestellt.

Den Versionssprung auf 18.1 hat Oracle übrigens über den “18 Geburtstag” von APEX erklärt.

Einen kurzen Überblick einiger neuer Funktionen finden Sie in dem Beitrag Neue Funktionen zum 18 Geburtstag.

Wenn Sie sich einen umfangreichen Eindruck über die technischen Möglichkeiten des neues Releases verschaffen möchten, können Sie sich, wie in dem Beitrag Installation Oracle Application Express 18.1 beschrieben eine eigene Entwicklungsumgebung einrichten.

 

Hier geht es zu den Neuerung von Oracle APEX 19.1

Update 04.04.2019

APEX Application Archive (Teil 1) – Installation und Anwendungen archivieren

Mit der Packaged Application “APEX Application Archive” lassen sich Backups Ihrer Anwendungen erstellen. Mit einigen kleinen Erweiterungen, können Sie diesen Prozess auch automatisieren. Wie Sie diese Anwendung einsetzen und entsprechend erweitern können, können Sie dieser dreiteiligen Artikel-Serie entnehmen.

Bei der Anwendung “APEX Application Archive” handelt es sich, wie auch bei der in diesem Artikel vorgestellten Anwendung QuickSql, um eine sogenannte Packaged Application. Oracle stellt mit den Packaged Applications den Nutzern von APEX einige nützliche Werkzeuge zur Verfügung, die Sie auch produktiv einsetzen können.

Das Programm “APEX Application Archive” dient, wie der Name schon erahnen lässt, der Sicherung und Archivierung von APEX-Anwendungen. Sie können mit diesem Programm Anwendungsarchive erstellen, die eine oder mehrere Programme eines Workspaces enthalten können. Gespeichert werden diese Archive in entsprechenden Tabellen der Datenbank.

Interressant ist diese Anwendung im Entwicklungsprozess. Sie können so eine Versionierung bzw. Archivierung von Zwischenständen durchführen. Natürlich ist das auch manuell über die Exportfunktion des Application Builder zu erreichen. Allerdings müssen Sie sich bei dieser Variante um eine entsprechende Ablagestruktur im Filesystem kümmern.

Leider sieht die Anwendung keine automatische, z.B. zeitlich geplante Archivierung vor. Dieses Manko möchte ich allerdings in einem der nachfolgenden Artikeln durch eine eigene Lösung beheben.

APEX Application Archive installieren

Die Installation einer Packaged Application geht recht einfach von der Hand.

Im Application Builder klicken Sie einfach auf die Schaltfläche “Packaged Application”.

APEX Packaged Application installieren
Abbildung 1: APEX Packaged Application installieren

In der nächsten Seite werden Ihnen alle Packaged Applications der aktuellen APEX-Version (hier 18.1 EA) aufgelistet.

Filtern Sie diese nach den produktiv einsetzbaren Anwendungen, erhalten Sie die folgende Auflistung.

Abbildung 2: Produktiv einsetzbare Packaged Applications

Jetzt müssen Sie die Anwendung APEX Application Archive auswählen und im nächsten Fenster auf Installation klicken. Folgen Sie dann einfach dem Installations-Wizzard und schließen Sie den Vorgang ab.

Abbildung 3: APEX Application Archive installieren

Nach erfolgreicher Installation der Anwendung werden Sie nach der Anmeldung mit Ihrem APEX-Account beim ersten Start noch gebeten einige Parameter festzulegen.

Abbildung 4: Parameter APEX Application Archive

Fertig.

Anwendungen archivieren

Nach der Einrichtung der Anwendung, sehen Sie das Dashboard des “APEX Application Archive” Programms.

 

Abbildung 5: Application Archive Dashboard

Nun können Sie das erste Anwendungsarchiv anlegen. Betätigen Sie einfach die Schaltfläche “Archive Applications”.

Abbildung 6: Anwendung selektieren

In diesem Schritt wählen Sie eine oder mehrere Anwendung aus dem aktuellen Workspace aus.

Klicken Sie auf Next > .

Abbildung 7: Kommentar einfügen

Jetzt noch ein paar hilfreiche Informationen ergänzen und das Archiv mit “Create Archive” erstellen.

Bitte beachten Sie, dass die so erstellten Archive lediglich die selektierten APEX-Anwendungen enthalten. Die zugehörigen Datenbankobjekte wie Tabellen, Views, Packaged,usw. sind nicht enthalten. Um ein möglichst vollständiges Abbild eines Entwicklungs(zwischen)standes einer Applikation zu erhalten, empfehle ich Ihnen, die notwendigen DDL-Skripte in den Supported Objects der APEX-Anwendung zu hinterlegen.

Alternativ können Sie auch ein Dump-file mittels expdp (bzw. exp) erzeugen. Dies bringt allerdings den Nachteil mit sich, dass Sie sich wieder selber um die Versionierung der Dateien kümmern müssen.

Teil 2-Wiederherstellen und Exportieren

Im nächsten Teil dieser Beitragsreihe wird es um das Zurücksichern und Exportieren einer Anwendung gehen.

Wenn es Sie interessiert, wie es weiter geht, bestellen Sie doch den Newsletter von INFORMATIK-TRANSPARENT oder schauen Sie später noch einmal hier vorbei.

Beitragsübersicht

[catlist name=”APEX Application Archive”]

 

 

 

APEX Application Archive (Teil 2) – Anwendungen wiederherstellen

Im zweiten Teil der Beitragsreihe zur “APEX Application Archive” -Anwendung, geht es um das Wiederherstellen und das Herunterladen der archivierten APEX Anwendungen.

Im ersten Teil der Reihe habe ich Ihnen gezeigt, wie Sie eine oder mehrere Anwendungen mit Hilfe des “APEX Application Archive” in einem Archive sichern können. Die Anwendungen speichert der “APEX Application Archiver” in der Tabelle APEX$ARCHIVE_CONTENTS in einem BLOB.

Um nun eine oder mehrere Anwendungen, die Sie so gesichert haben, wiederherzustellen,  können Sie auf zweierlei Arten vorgehen.

Für beide Varianten ist der Ausgangspunkt der Menüeintrag “Archived Content”. Über diesen gelangen Sie zu einem Interaktiven Grid, welches alle archivierten Applikationen auflistet.

Abbildung 8: Anwendungsarchiv auswählen

Hier können Sie über das Setzen entsprechender Filter die benötigte Version der Anwendung auswählen.

APEX-Anwendung wiederherstellen

Als erste Möglichkeit können Sie eine archivierte Anwendung direkt aus einem Archiv heraus recovern. Dazu sind aber einige Schritte notwendig.

Suchen Sie in der Tabelle “Archived Content” die wiederherzustellen dies  Anwendung. Klicken  Sie auf den  Button “Restore”, so wird Ihnen auf der nächsten Seite des Wizzards eine Zusammenfassung der gewählten Anwendungen präsentiert.

Abbildung 9: Restore Content

Wie in Abbildung 9 dargestellt, starten Sie die Extraktion über “Restore Content”.

Jetzt wird die Exportdatei aus dem Archiv geladen und direkt in Ihrem Workspace in das sogenannte “Export Repository” importiert.

Anschließend bekommen Sie eine Checkliste angezeigt, die Ihnen die nächsten Schritte zur Installation der Anwendung erklärt.

Abbildung 10: Checkliste Installation der Anwendung

Wechseln Sie nun in die APEX-Entwicklungsumgebung und dort in den “Application Builder” des zugehörigen Workspaces. Klicken Sie auf “Utilities”.

Abbildung 11: Export Repository

Wie in Abbildung 11 dargestellt geht es weiter über den Link Export.

Abbildung 12: APEX-Anwendung installieren

Danach betätigen Sie den Link “Export Repository”.

Abbildung 13:Export Repository

Nun öffnet Sie das Export Repository. In dieser Tabelle sehen Sie die zuvor extrahieren Version Ihrer Anwendung(en). Über den Link “Install” starten Sie den Anwendungs Import-Assistenten.

Dieser stellt Ihnen verschiedene Möglichkeiten zur Verfügung. So können Sie die Anwendung parallel zu der aktuellen Anwendung installieren. Der eigentliche Ablauf ist im Abschnitt “Install Database Application” beschrieben.

APEX-Anwendung herunterladen

Bei der zweiten Variante können Sie einfach ein Archiv selektieren und die gewünschten Anwendung als APEX-Exportfile herunterladen. Diese Datei können Sie dann über die Importfunktion des Application-Builders importieren.

Dabei gehen Sie so vor.

Der Ausgangspunkt ist wieder, wie bereits in Abbildung 8 gezeigt, der Menüpunkt “Archived Content”. Dort suchen Sie sich wieder die Anwendungsversion, die Sie herunterladen möchten.

Klicken Sie hier auf “Download”.

Jetzt wird die Anwendung als Exportfile über Ihren Browser heruntergeladen. Diese Datei können Sie nun in einem beliebigen Workspace importieren.

Dazu melden Sie sich an der APEX-Entwicklungsumgebung an und öffnen dort den “Application Builder”.

Im “Application Builder” gelangen Sie über das Icon “Import” zum Import-Wizzard.

Hier können Sie die eben extrahierte Datei auswählen. Den File Type belassen Sie bei “Database Application,…”. Über Next> gelangen Sie zur nächsten Seite des Import-Assistenten.

Wie bereits erwähnt, verläuft die Installation einer Anwendung bei beiden Varianten ab diesem Punkt gleich.

Install Database Application

Im Installations-Wizzards können Sie, wie in der Abbildung 14 gezeigt, festlegen, ob Sie die Anwendung mit der ursprünglichen oder einer neuen App-ID automatisch oder manuell versehen lassen möchten. Je nach Auswahl wird die vorhandene Version der Anwendung überschrieben oder als parallele Version installiert.

Abbildung 14: Import Database Application

Über “Install Application” geht es zum nächsten Schritt. Hier müssen Sie noch die Frage beantworten, ob Sie die “Supported Objects” installieren möchten.

Bei den “Supported Objects” handelt es sich  meist um DDL-Skripte, welche bei der Installation bzw. Update oder auch Deinstallation ausgeführt werden.  Diese “Supported Objects” sind Bestandteil einer Anwendung.

Hier sollten Sie sich im Klaren darüber sein, ob diese SQL- Skripte ausgeführt werden sollen. Im Zweifelsfall können Sie sich diese Skripte über den etwas versteckten Bereich Tasks in dieser Seite anzeigen lassen. Nach dem aufklappen der Tasks klicken Sie dazu einfach auf den Link “Preview Installation Script”. In dem sich nun öffnenden Fenster sind alle Skripte einsehbar.

Jetzt müssen Sie den Wizzard nur noch bis zu Ende folgen und dabei die Installation abschließend bestätigen.

APEX Application Archive (Teil 3) – Automatisieren mit dem dbms_scheduler

Im dritten Teil der Beitragsserie wird es um die automatische Erzeugung von Anwendungsarchiven gehen. Nutzt man darüber hinaus noch die Metadaten des APEX -Repositories, so lässt sich der Vorgang auch noch etwas smarter gestalten.

Beitragsübersicht

[catlist name=”APEX Application Archive”]

 

 

 

 

 

APEX Application Archive (Teil 3) – Automatisieren mit dem dbms_scheduler

Im dritten Teil der Beitragsserie geht es um die automatische Erzeugung von APEX-Anwendungsarchiven. Nutzt man darüber hinaus noch die Metadaten des APEX-Repositories, so lässt sich der Vorgang auch noch etwas smarter gestalten.

APEX-Anwendungen  sichern via. PL/SQL

Zu Beginn geht es darum herauszufinden, welche PL/SQL Funktion benötigt wird, um eine Anwendungsarchiv zu erzeugen.

Da die Funktion bereits in der Packaged Application “APEX Application Archive” genutzt wird, können Sie sich diese einmal ansehen.

Hierzu begeben Sie sich einfach in die Verwaltung der Packaged Applications.

Öffnen Sie dort die “APEX Application Archive”  und klicken Sie auf den Button “Manage’.

Abbildung 14: Unlock Application

Folgen Sie dem Wizzards und Entsperren Sie die Anwendung.

Jetzt können Sie die Anwendung wie gewohnt über den Application Builder bearbeiten.

Öffnen Sie die Seite 9. Dort finden Sie den Prozess der für die Archivierung der Anwendungen zuständig ist.

Abbildung 15: Archive Application

Der besseren Lesbarkeit wegen, habe ich Ihnen den Quellcode einmal heraus kopiert.

DECLARE
  l_vc_arr2 APEX_APPLICATION_GLOBAL.VC_ARR2;
  l_hdr_id number;
  z integer;
BEGIN
  l_vc_arr2 := APEX_UTIL.STRING_TO_TABLE(ltrim(rtrim(:P10_APPLICATIONS_TO_ARCHIVE,':'),':'));

  l_hdr_id := apex_cloud_archive.create_header(
                  p_workspace_id = :flow_security_group_id,
                  p_version = 1,
                  p_archive_name = :P5_ARCHIVE_NAME,
                  p_comments =:P9_COMMENTS);

  FOR z IN 1..l_vc_arr2.count LOOP
    apex_cloud_archive.archive_applications(
       p_workspace_id = :flow_security_group_id,
       p_header_id = l_hdr_id,
       p_application_id = l_vc_arr2(z));
  END LOOP;
END;

Quellcode 1: Auszug aus Seite 9 der Oracle APEX Anwendung Archive Application

Wie Sie dem Listing entnehmen können, benötigen Sie die Funktion create_header und archive_applications.

Die Funktion create_header legt ein neues Archiv an. Diesem Archiv können Sie nun mit Hilfe der Prozedur archive_applications eine oder mehrere Anwendungen hinzufügen.

Abbildung 16: APEX Views – APEX_APPLICATIONS

Die Parameter, die Sie für den Aufruf der beiden Prozeduren benötigen, liefert die APEX-View APEX_APPLICATIONS.

Um beispielsweise die “Sample Database Application” mit der App-Id 507 zu sichern, können Sie folgenden PL/SQL Block ausführen.

Abbildung 17: Anwendung via. API archivieren

Ein Hinweis am Rande. Oracle schreibt auf https://apex.oracle.com/de/  (Stand 22.05.2018 ) folgendes zum Anpassen von Packaged Applications.

“[..] Application Express bietet eine Sammlung von 35 Geschäfts- und Beispielsanwendungen. Sie können diese Anwendundungen für Produktionszwecke einsetzen oder kopieren, editieren und als Grundlage für Ihre eigenen Anwendungen verwenden.[..]”

Smarte Sicherung durch Nutzung der APEX-Views

Kombiniert  man nun die APEX-View APEX_APPLICATIONS mit den Tabellen der Anwendung “Application Archive” kann man den Prozess noch etwas smarter gestalten. Über das folgende select-Statement ermitteln Sie notwendigen Parameter. Dabei wird allerdings geprüft, ob seit der letzten Archivierung überhaupt Änderungen an der zu sichernden Anwendung durchgeführt wurden.


select WORKSPACE_ID,APPLICATION_ID, APPLICATION_NAME
  from APEX_APPLICATIONS a
  where APPLICATION_ID = 507
    and not exists (
              select 'X'
               from "APEX$ARCHIVE_CONTENTS" "APEX$ARCHIVE_CONTENTS",
                    "APEX$ARCHIVE_HEADER" "APEX$ARCHIVE_HEADER"
               where "APEX$ARCHIVE_HEADER".ID="APEX$ARCHIVE_CONTENTS".HEADER_ID
                 and "APEX$ARCHIVE_HEADER".WORKSPACE_ID = a.WORKSPACE_ID
                 and "APEX$ARCHIVE_CONTENTS".APP_ID = a.APPLICATION_ID
                 and "APEX$ARCHIVE_HEADER".CREATED > a.last_updated_on)

Quellcode 2: Änderungen berücksichtigen

Jetzt können Sie diese Erkenntnisse in Form einer Prozedur in der Datenbank speichern.


create or replace procedure back_app
(p_app_id number)
is
  l_hdr_id number;
  l_workspace_id number;
  l_archive_name varchar2(200);
BEGIN

for c in (select WORKSPACE_ID, APPLICATION_NAME
           from APEX_APPLICATIONS a
          where APPLICATION_ID = p_app_id
            and not exists (
                 select 'X'
                  from "APEX$ARCHIVE_CONTENTS" "APEX$ARCHIVE_CONTENTS",
                       "APEX$ARCHIVE_HEADER" "APEX$ARCHIVE_HEADER"
                   where "APEX$ARCHIVE_HEADER".ID = "APEX$ARCHIVE_CONTENTS".HEADER_ID
                     and "APEX$ARCHIVE_HEADER".WORKSPACE_ID = a.WORKSPACE_ID
                     and "APEX$ARCHIVE_CONTENTS".APP_ID = a.APPLICATION_ID
                     and "APEX$ARCHIVE_HEADER".CREATED > a.last_updated_on))
loop
  l_workspace_id := c.WORKSPACE_ID;
  l_archive_name := c.APPLICATION_NAME;

  l_hdr_id := apex_cloud_archive.create_header(
               p_workspace_id => l_workspace_id ,
               p_version => 1,
               p_archive_name => l_archive_name || to_char(sysdate,'dd.mm.yyyy'),
               p_comments => '' );

apex_cloud_archive.archive_applications(
               p_workspace_id => l_workspace_id ,
               p_header_id => l_hdr_id,
               p_application_id => p_app_id );
end loop;

END;

Quellcode 3: Prozeduren back_app

Um nun eine Anwendung zu archivieren genügt folgender Aufruf.

BEGIN
  back_app(507);
END

Quellcode 4: Anwendung archivieren

Sicherungen Automatisieren  mit dem dbms_scheduler

Gerade im Rahmen der Entwicklung einer Anwendung ist es oft nützlich, auf ältere Versionen einer Anwendung zurückgreifen zu können. Um das Archivieren nicht immer manuell anstoßen zu müssen, können Sie die eben konzipierte Prozedur back_app über einen Scheduler ausführen. Am einfachsten geht das über das Package dbms_schedule.


BEGIN
  DBMS_SCHEDULER.CREATE_JOB (
     job_name => 'my_backup_job1',
     job_type => 'PLSQL_BLOCK',
     job_action => 'BEGIN back_app(507); END;',
     start_date => sysdate,
     repeat_interval => 'FREQ=DAILY; BYHOUR=10,15,20;',
     end_date => sysdate + 1,
     enabled => TRUE,
     comments => 'sample app');
END;
/

Quellcode 5: Regelmäßige Sicherung

In diesem Beispiel wird die Anwendung 507 jeden Tag um 10:00, 15:00 und 20:00 immer dann gesichert, wenn die Anwendung seit der letzten Archivierung geändert wurde.

Um nun eine Anwendung wieder herzustellen, gehen Sie wie in Teil 2 dieser Reihe beschrieben vor.

Beitragsübersicht

[catlist name=”APEX Application Archive”]

 

Neue Funktionen zum 18ten – Oracle APEX 18.1 Early Adopter 2

Oracle “feiert” den 18 Geburtstag von Apex mit der Veröffentlichung der Version 18.1. Unter https://apexea.oracle.com können Sie diese Version ausprobieren. Die passenden Beta-Doku gibt es auch schon.

Darüber hinaus gibt es eine Vorabversion der Javascript-API-Dokumentation.

Die Version 18.1 erweitert die Funktionen der Version 5.2 in diversen Bereichen. In den Releasenotes listet Oracle  diese auf. Im Folgenden finden Sie eine erste Zusammenfassung interessanter Punkte und erste Impressionen dazu.

Oracle REST-Data Services

Im Bereich des REST-Services sind einige, gerade im Cloud Bereich nützliche Neuerungen dazu gekommen.

REST-Data Services

Über das PL/SQL Package APEX_EXEC lassen sich SQL-Queries und PL/SQL Blöcke in entfernten Oracle-Datenbanken aufrufen.

In den Shared Components können Sie jetzt die Referenzen der zu konsumierenden  REST-Services (Web Source Modules) verwalten. Diese Web-Sources sind als Datenquelle in verschiedenen Regionen und Items verwendbar. Durch die verbesserte Funktionalität können auch nicht Oracle-Datenbank Systeme in APEX- Anwendungen einfacher integriert werden.

App-Wizzard

Wie bereits in der Version 5.2 erkennbar war, wurde der App-Wizzard deutlich umgestaltet. Neben einem kompakteren Design, bietet er jetzt die Möglichkeit aus einer reichhaltigen Palette komplette Features wie den Zugriff auf die Benutzerverwaltung, Zugriffsstatistiken, eine (neue) Feedback-Funktion, usw. in eigene Anwendungen zu integrieren.

App-Wizzard APEX 18.1 EA
App-Wizzard APEX 18.1 EA

In der Anwendung finden sich diese dann in einem eigens erstellten Menüpunkt “Administration”.

APEX-APP Eigenschaften

JET Charts

Es wurden diverse neue JET Charts in die neue APEX Version eingebaut. Sie können sich eine wirklich schöne Übersicht der echt beachtlichen Chart-Type über die Packaged Application “Sample Charts” verschaffen.

Packaged Application: Sample Charts

Das neue APEX  18.1 bringt jetzt z.B. Pyramiden-Charts mit.

Oracle JET: Pyramid

Auch Box-Plots sind nun mit an Bord:

Oracle JET: Box Plot

Interaktives Grid

Auch bei dem Interaktiven Grid gibt es interessante Neuerungen.

Es wird nun des Herunterkopieren von Daten unterstützt.
Auch das Kopieren in die Zwischenablage (für Zeilen- oder Zellbereichsselektionen) ist jetzt möglich.

Interaktives Grid: Copy to Clipboard

 

Hier geht es zu den Neuerung von Oracle APEX 19.1

Update 10.04.2019

Oracle Application Express – Quick SQL

Low Code Entwicklung von Datenmodellen mit Quick SQL, einer APEX Packaged Application.

Oracle bietet im Rahmen seiner Entwicklungsumgebung APEX sogenannte Packaged Applications. Bei diesen Anwendungen handelt es sich zum Einen um Bespielanwendungen zum Anderen aber auch um produktiv nutzbare Systeme.

Eine dieser Anwendungen ist Quick SQL.

Quick SQL einrichten

Die Installation von Quick SQL geht zügig von der Hand. In APEX angemeldet, klicken Sie auf den Menüpunkt Packed Application.

APEX Packaged Application (Mitgelieferte Anwendungen)

Nun können Sie in der sich öffnenden Übersicht die Packaged Application Quick SQL auswählen.

Quick SQL auswählen

Neben einer Kurzbeschreibung finden Sie auf der sich öffnenden Seite die Schaltfläche Installieren. Folgen Sie dem Installationsassistenten. Fertig.

Starten Sie die Anwendung das erste mal, können Sie sich mit dem bei der Installation gewählten Authentifizierungsverfahren an Quick SQL anmelden. Bei dem ersten Start, müssen Sie noch einige Parameter prüfen und bei Bedarf anpassen. Das stellt sich wie in folgender Abbildung  dar.

QuickSQL einrichten

Datenmodell mit Quick SQL entwerfen

Quick SQL gliedert sich in  zwei Bereiche. Links können Sie sehr kompakt Tabellen und ihre Relationen zueinander definieren.

Rechts wird bei jeder Änderung das zugehörige DDL (Data Definition Language) Skript erzeugt.

Benutzeroberfläche QuickSQL

Als einfaches Beispiel soll ein Datenmodell für ein Projektplanungstool dienen.

Tabellen werden einfach durch die Eingabe des Tabellennamens deklariert. Die zugehörigen Spalten rücken Sie einfach in den folgenden Zeilen ein.

Datenmodell Projektplanung

Quick SQL Eigenschaften

Schauen Sie sich das erzeugte DDL-Script näher an, so sehen Sie, dass eine ID-Spalte als künstlicher Schlüssel erzeugt wurde.  Diese Spalte wird über einen Trigger gefüllt. Auch gibt es mehrere Spalten, in denen Audit-Informationen gespeichert werden. Diese Spalten können beim Einsatz der Tabelle in einer APEX-Anwendung sogar mit den APEX-Account über einen Trigger belegt werden. Dies sind nur zwei Beispiele, die Ihnen Quick SQL bietet. Festlegen können Sie die Generierung dieser Funktionen in den Eigenschaften von Quick SQL.

Quick SQL Eigenschaften

Die Abbildung zeigt nur einen Teil der Möglichkeiten. So können Sie z.B. allen Tabellen einen Präfix voran stellen, Änderungen automatisch über einen Trigger in einer Audit-Tabelle protokollieren und noch vieles mehr erledigen lassen. Nehmen Sie sich Zeit, um diese Möglichkeiten in Gänze kennen zu lernen.

Relationen

Jedem Projekt sollen in dem gezeigten Beispiel n ToDos zugeordnet werden können. Also eine einfache 1:n Beziehung.

Um diese abhängige Tabelle zu erzeugen, geben Sie auf der Ebene der Spalten zunächst ToDos als neuen Tabellennamen ein. In den nächsten Zeilen rücken Sie die Spaltenbezeichner um eine weitere Ebene tiefer ein. Quick SQL erweitert das DDL-Script um die Tabelle ToDos und fügt eine Fremdschlüsselspalte project_id ein.  Neben der Spalte wird auch sofort ein foreign key constraint erzeugt.

Relationen erzeugen

Syntax and Examples

Nähere Informationen über die sehr umfangreichen Möglichkeiten von Quick SQL verbergen sich hinter dem Link Syntax and Examples in der Anwendung.

Fazit

Quick SQL bietet als Low Code Entwicklungstool durch die Nutzung von Konventionen eine enorme Geschwindigkeit bei der Erstellung eines Datenmodells. Auch für nicht APEX-Entwickler verdient diese Anwendung eine genauere Betrachtung.