ARTA Entwurf und Implementierung einer - IDB

Werbung
Rheinische Friedrich-Wilhelms-Universität Bonn
Institut für Informatik III
ARTA
Entwurf und Implementierung einer Triggersprache mit
Zeitereignissen für Access-Datenbanken
Diplomarbeit von
Kazem Fadaei
August 2002
Betreuer: Prof. Dr. Rainer Manthey
Inhaltsverzeichnis
1 Einleitung
1
2 Grundlagen von Datenbanken
2.1 Aktive Datenbanken . . . . . . . . . . . .
2.2 Trigger in SQL3 . . . . . . . . . . . . . . .
2.2.1 Syntax von SQL3-Triggersprache .
2.2.2 Semantik von SQL3-Triggersprache
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5
8
11
11
13
3 Visual Basic for Applications
3.1 Sprachgrundlagen . . . . . . . . . . .
3.2 Module, Klassenmodule und Objekte
3.3 API . . . . . . . . . . . . . . . . . .
3.4 Fehlerbehandlung in VBA . . . . . .
3.5 Transaktionen in VBA . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
17
18
20
23
26
29
.
.
.
.
31
31
33
36
38
.
.
.
.
.
.
39
39
47
49
51
53
58
. . . . . . . . . . . . . . . . . . . . . .
63
63
4 MS-Access
4.1 Tabellen und Beziehungen
4.2 Formulare . . . . . . . . .
4.3 Datenzugriffsobjekte . . .
4.4 Sicherheit . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5 Konzept
5.1 Das Konzept eines Präprozessors . . . .
5.2 Syntax von ARTA-Triggersprache . . . .
5.2.1 Syntax eines Triggers . . . . . . .
5.2.2 Syntax eines Eventmusters . . . .
5.3 Semantik der ARTA-Triggerbearbeitung
5.4 Verwaltung von Zeitereignissen . . . . .
6 Implementierung
6.1 Architektur von ARTA
I
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
6.2
6.3
6.4
6.5
6.6
6.7
Benutzeroberfläche . . . . . . . . . . . . . . .
6.2.1 Verwaltung von Triggern . . . . . . . .
6.2.2 Verwaltung von Ereignismustern . . . .
Speichern von Regeln . . . . . . . . . . . . . .
Klassen, Module und Objekte von ARTA . .
6.4.1 Klassenmodule . . . . . . . . . . . . .
6.4.2 Module und Objekte . . . . . . . . . .
Befehlsausführungssystem . . . . . . . . . . .
Fehlerbehandlung . . . . . . . . . . . . . . . .
Besondere Aspekte . . . . . . . . . . . . . . .
6.7.1 Trigger Execution Context . . . . . . .
6.7.2 Timer . . . . . . . . . . . . . . . . . .
6.7.3 Behandlung vergangener Zeitereignisse
7 Zusammenfassung und Ausblick
II
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
65
67
68
70
72
72
75
77
79
81
81
84
86
89
Kapitel 1
Einleitung
Das MSr1 Access-Datenbankmanagementsystem ist ein relationales und passives Datenbankmanagementsystem. In einem passiven Datenbankmanagementsystem werden Operationen ausgeführt, die unmittelbar von Anwendern oder
einem Programm angefordert werden. In einem aktiven Datenbankmanagementsystem können aber auch Situationen beschrieben werden, bei denen das Datenbankmanagementsystem automatisch reagiert. Eine Situation in einer Datenbank ist eine Kombination aus einem Datenbankzustand und einem Ereignis.
In einem aktiven Datenbankmanagementsystem werden in diesem Sinne interessante Situationen mit Hilfe von aktiven Regeln beschrieben. Aktive Regeln
werden auch als ,,Trigger” bezeichnet. Eine aktive Regel besteht aus drei Teilen: Ereignisteil (Event), Bedingungsteil (Condition) und Aktionsteil (Action).
Aktive Regeln werden deswegen auch als ECA-Regeln bezeichnet. Ereignisse treten entweder bei Datenbankänderungen (Änderungsereignis) oder bei Erreichen
eines bestimmten Zeitpunktes (Zeitereignis) ein. Ein aktives Datenbankmanagementsystem soll Anwendern Werkzeuge anbieten, mit deren Hilfe sie Trigger
definieren können. Trigger ist eine andere Bezeichnung zu aktiven Regeln. Dazu
soll ein aktives Datenbankmanagementsystem auch Ereignisse erkennen und die
Trigger bearbeiten, die durch diese Ereignisse gefeuert werden.
In der vorliegenden Arbeit wird es darum gehen, das Access-Datenbankmanagementsystem um eine Triggersprache zu erweitern und diese Erweiterung zu implementieren. Die Erweiterung von Access um eine Triggersprache
wird in Form einer Access-Anwendung realisiert. Eine Access-Anwendung ist
eine Software, die in der Programmiersprache VBA2 unter Einsatz von AccessKomponenten programmiert wird. Eine Access-Anwendung ist auf das Access1
MS ist die Abkürzung für Microsoft. Im weiteren Verlauf der Arbeit wurde auf das Copyright Symbol von Microsoft verzichtet.
2
Visual Basic for Applications
1
2
KAPITEL 1. EINLEITUNG
Programm angewiesen und kann nur unter diesem Programm ausgeführt werden.
Das Konzept der in dieser Arbeit vorgestellten und implementierten Triggersprache basiert auf SQL3-Standard. In SQL3 sind Trigger aktive ECA-Regeln,
die alle eindeutig benannt sind. In SQL3 wird nur das Auftreten von Änderungsereignissen (ON DELETE, ON INSERT und ON UPDATE) erkannt. Mit
der hier vorgestellten und implementierten Triggersprache werden zusätzlich
auch Zeitereignisse (absolute und periodische) berücksichtigt. Ein absolutes Zeitereignis tritt nur einmal durch Erreichen eine bestimmten Zeitpunktes ein. Ein
periodisches Zeitereignis tritt wiederholt und regelmäßig in gleichen Zeitabständen ein.
Zusätzlich zu absoluten und periodischen Zeitereignissen existiert noch ein
weiterer Zeitereignistyp: relative Zeitereignisse. Ein relatives Zeitereignis wird
durch eine Kombination aus einem absoluten bzw. periodischen Zeitereignis
mit einer Zeitdauer spezifiziert, z.B. ,,am zweiten Tag der Schulferien” oder
,,letzten Montag jedes Monats”. Zeitereignisse sind vor allem in objektorientierten Datenbanksystemen realisiert worden, z.B. HiPAC3 (High Performance Active Database System), Ode4 , SAMOS5 (Swiss Active Mechanism Based
Object-Oriented Database Systems). In den meisten dieser Systeme werden alle
Zeitereignistypen, ,,absolut”, ,,periodisch” und auch relativ spezifiziert.
Für jedes Zeitereignismuster soll in dieser Arbeit eine Deadline mit der Einheit ,,Minute” definiert werden. Mit Zuordnung einer Deadline zu einem Zeitereignis(muster) wird angegeben, dass die Bearbeitung von (durch dieses Zeitereignis gefeuerten) Triggern innerhalb dieser deadline angefangen werden muss.
Nach Ablauf dieser Deadline wird das Auftreten dieses Zeitereignisses ignoriert
und dessen Trigger werden nicht mehr bearbeitet. Um das Konzept von Zeitereignissen in dieser Arbeit zu implementieren, werden Prozeduren der API6 Schnittstelle eingesetzt. Mit Hilfe von API-Schnittstelle werden Timer gesetzt,
die in separaten Prozessen im Betriebsystem laufen und deswegen die Datenverarbeitung (in Access) und deren Geschwindigkeit nicht beeinträchtigen.
Für das in dieser Arbeit implementierte System wurde der Name ARTA
(Active Real Time Access Database system) ausgewählt. Bei einem ARTATrigger wird eine Parameterübergabe vom Bedingungsteil an den Aktionsteil
3
Vgl. [AKHaWi]
Vgl. [AKHaWi]
5
Vgl. [AKPat12]
6
Application Programming Interface
4
3
möglich sein, nachdem Parameter eindeutig für den Trigger definiert (deklariert)
wurden. Diese Parameter dürfen nur bei Änderungsereignismustern eingesetzt
werden.
Im Kapitel 2 geht es um die Grundlagen von Datenbanken und im Besonderen von aktiven Datenbanken. Anschließend wird ein kurzer Exkurs zu Echtzeitsystemen (Real Time Systems) und aktiven Echtzeitdatenbanksystemen (Aktive
Real Time Database systems) gegeben. In Kapitel 3 wird die Programmiersprache VBA und deren Einsatz in Access dargestellt. Access und seine Komponenten werden im Kapitel 4 untersucht. Formularklassenmodule und Formularereignisse, die bei der Implementierung von ARTA eine wichtige Rolle spielen, werden
besonders beschrieben. Das Konzept für ein aktives Access-Datenbankmanagementsystem ist Thema von Kapitel 5. Dort wird gezeigt, dass aufgrund der
Ereigniserkennungsproblematik, besonders bei Änderungsereignissen, der Entwurf eines Präprozessors in Form einer Access-Anwendung unvermeidbar ist. Im
Kapitel 6 werden die bei der Implementierung von ARTA angewandten Methoden beschrieben. Im weiteren werden die ARTA-Klassen(module) und die aus
diesen Klassen initiierten Objekte beschrieben, die bei der Implementierung von
ARTA eingesetzt werden. Das Kapitel 7 gibt eine Zusammenfassung, der einige
Vorschläge zur Weiterentwicklung der Arbeit folgen.
4
KAPITEL 1. EINLEITUNG
Kapitel 2
Grundlagen von Datenbanken
In diesem Kapitel werden Grundbegriffe von Datenbanken beschrieben. Industrie und Forschung sehen sich heute mit gewaltigen Mengen von Informationen
konfrontiert und werden von der sogenannten Informationsflut überrollt. Dabei
lässt sich in jeder Hinsicht darüber streiten, wie der Begriff ,,Information” zu
definieren ist. Für diese Arbeit soll die folgende Erklärung genügen: ,,Information” ist jede Art von Wissen, das für eine Gruppe von Menschen von Interesse
ist und verwaltet werden kann. Beispielsweise sind diese Informationen über Telefonkunden einer Telefongesellschaft, Informationen über genetische Merkmale
von Menschen (eines Landes), Informationen über Diplomanden an der Universität Bonn.
Informationen dieser Menge können nicht mehr ausschließlich mit traditionellen Methoden verwaltet werden. Diese können z.B. nicht mehr nur als Dokumente irgendwo archiviert werden, da sie später - nicht zuletzt aufgrund ihres
Umfanges - nur mit großem Aufwand wieder auffindbar sind. Heutzutage bieten
Computer die Möglichkeit Informationen platzsparender zu bewahren und sie
mit hoher Geschwindigkeit wieder aufzufinden; An dieser Stelle kommen Begriffe
wie ,,Datenbank”, ,,Datenbanksystem” und ,,Datenbank Mangement System”
ins Spiel.
Eine Datenbank ist eine Sammlung von zusammengehörenden Informationen, z.B. Informationen über Kontoinhaber einer Bankfiliale oder Informationen
über die eingeschriebenen Informatikstudenten an der Universität Bonn. Eine Datenbank wird indirekt von einem Mensch verwaltet. ,,Indirekt” bedeutet,
dass der Datenbankbenutzer einem System seine Anforderungen angibt. Danach
werden diese Anforderungen in dem System überprüft und ausgeführt. Dieses
System ist eine Software, die ,,Datenbank Management System” (DBMS) genannt wird. Das Datenbankmanagementsystem darf nicht von Daten (Informa5
6
KAPITEL 2. GRUNDLAGEN VON DATENBANKEN
tionen) abhängig sein, d.h. ein Datenbankmanagementsystem muss in der Lage
sein jede Art von Daten zu speichern, und soll dem Benutzer die notwendigen
Mechanismen anbieten, um diese Daten verwalten zu können. Die Kombination
eines Datenbankmanagementsystems mit mehreren Datenbanken nennt sich ein
Datenbanksystem. Das Bild 2.1 stellt ein Datenbanksystem (DBS) dar, das
aus einem Datenbankmanagementsystem (DBMS) und mehreren Datenbanken
(DBn ) besteht.
Benutzer
DBS
DBMS
DB 1
DB 2
...
DB n
Abbildung 2.1: Datenbankmanagementsystem und Datenbanksystem
Außer Anwendungsunabhängigkeit bzw. Datenunabhägigkeit zeichnet sich
ein Datenbankmanagementsystem besonders durch die folgenden Eigenschaften
aus:
• Dauerhaftigkeit:
Ein Datenbankmanagementsystem hat die Aufgabe, die Daten solange
aufzubewahren, bis sie von einem Benutzer absichtlich gelöscht werden.
Die Daten in einer Datenbank dürfen nicht ohne direkte oder indirekte
Benutzeranforderung gelöscht werden bzw. verloren gehen.
• Integrität:
Eine Datenbank darf keine unsinnigen (inkonsistenten) Daten beinhalten,
d.h. die Daten müssen der Realität entsprechen. Ein Datenbankmanagementsystem soll dem Benutzer Werkzeuge anbieten, mit deren Hilfe er
Integritätsregeln aufstellen kann. Nach der Definition der Integritätsregeln wird ein Datenbankmanagementsystem beachten, dass keine Daten
entstehen können, die diesen Regeln widersprechen.
7
• Benutzerfreundlichkeit:
Ein Datenbankmanagementsystem sollte so einfach wie möglich zu bedienen sein. Das bedeutet, dass dem Endbenutzer eine Sprachschnittstelle
zur Verfügung gestellt wird. Dabei soll ein Datenbankmanagementsystem
auch in der Lage sein, die Nutzung der Datenbank von mehreren Benutzern zu ermöglichen.
Das relationale Model ist das in heutigen Datenbankmanagementsystemen
am weitesten verbreitete Datenmodel. Eine Datenbank im relationalen Model
bezeichnet man als eine relationale Datenbank. Im Falle einer relationalen Datenbank besteht diese aus einer Anzahl von ,,Relationen”. Eine Relation bezeichnet auch eine ,,Datenbasis” einer relationalen Datenbank. Jede Relation
ist eine Menge von Tupeln. Ein Tupel ist ein Datensatz, der aus Attributen
besteht. Ein Datensatz ist ein atomares Element einer Relation. Jede Relation
erfüllt die Bedingung, keine zwei gleichen Tupeln besitzen zu dürfen. Jede Relation hat einen eindeutigen Namen innerhalb einer Datenbank. Jedes Attribut
der Tupel einer Relation hat einen eindeutigen Namen innerhalb der Relation.
Die Reihenfolge von Tupeln in einer Relation sind nicht zu beachten. Eine Relation kann als eine Tabelle angesehen werden, deren Zeilen die Tupeln und deren
Spalten die Attribute repräsentieren.
Name
Fadaei
Herrmann
Schmidt
Schumacher
...
Vorname
Kazem
Joachim
Michael
Beate
...
Student
Mtr.Nr
Email
658698
[email protected]
19911000 [email protected]
19951000
[email protected]
21869458 [email protected]
...
...
Beispiel 2.1: Die Studenten-Tabelle
In dem Beispiel 2.1 ist eine Relation in Form einer Tabelle gegeben. Die Tabelle
enthält Informationen über eine Anzahl von Studenten. Jede Zeile repräsentiert
Informationen über eine Studentin bzw. einen Studenten. Die Informationen jeder Zeile teilen sich in vier Teile, die verschiedene Attribute zu jedem Datensatz
beinhalten.
8
KAPITEL 2. GRUNDLAGEN VON DATENBANKEN
2.1
Aktive Datenbanken
In der Regeln verhalten sich die traditionellen Datenbanken passiv. In einer
passiven Datenbank wird jede Operation (vor allem delete, insert bzw. update) nur dann ausgeführt, wenn sie unmittelbar von einem Benutzer oder einem
Programm angefordert wird. Von aktiven Datenbanken wird erwartet, auf bestimmte Situationen in einer Datenbank automatisch zu reagieren und bestimmte Aufgaben zu erledigen.
,,Ein Datenbanksystem heißt aktiv, wenn es zusätzlich zu den üblichen (passiven) DBS-Fähigkeiten in der Lage ist, definierbare Situationen in der Datenbank (und wenn möglich darüber hinaus) zu
erkennen und als Folge davon bestimmte (ebenfalls definierbare) Reaktionen auszulösen.”1
Ein aktives Datenbankmanagementsystem soll dem Benutzer einen Mechanismus anbieten, um dem Datenbankmanagementsystem mitteilen zu können,
in welcher Situation welche Operation auszuführen ist. Es stellt dazu eine Regelsprache zur Verfügung, mit deren Hilfe sogenannte aktiven Regeln definiert
und in einer bestimmten Form (Wissensmodel) gespeichert werden können.
Eine aktive Regel besteht aus drei Teilen: Ereignisteil (Event), Bedingungsteil (Condition) und Aktionsteil (Action). Die aktiven Regeln heißen deswegen
ECA-Regeln. Eine andere Bezeichnung für aktive Regeln ist das Wort ,,Trigger”. Die Menge aller aktiven Regeln in einer Datenbank heißt Regelbasis.
Mit der Definition einer Regel wird das Datenbanksystem aufgefordert, beim
Eintreffen des Ereignisses E die Aktion A auszuführen, wenn die Bedingung C
erfüllt ist. Die Kombination aus Ereignis und Bedingung eines Triggers bezeichnet eine für den Trigger ,,interessante Situation”, bei der die Triggeraktion
ausgeführt werden soll. Trifft das Ereignis E ein, so ist die Regel (der Trigger)
mit dem Ereignisteil E zu feuern (bzw. auszulösen oder zu triggern).
Ereignis: Ein Ereignis ist ein Geschehen in einer Datenbank an einem bestimmten Zeitpunkt2 : ein punktuelles Geschehen. Ein Ereignis kann primitiv
oder zusammengesetzt sein.
• Primitive Ereignisse sind einfache bzw. atomare Ereignisse, z.B. ,,ON
DELETE FROM tablename”.
1
2
[AKDiGa], S.7.
[AKPaDi]
2.1. AKTIVE DATENBANKEN
9
• Zusammengesetzte Ereignisse sind Ereignisse, die sich aus mehreren
primitiven Ereignisse unter Benutzung von Verknüpfungsoperationen3 bilden, z.B. ,,ON INSERT TO table1 AND ON UPDATE OF table2 ”.
Ein primitives Ereignis kann wiederum entweder ein Datenbankereignis (Änderungsereignis) oder ein Zeitereignis sein. Ein Datenbankereignis tritt bei Änderung an einer Tabelle bzw. an einem Feld dieser Tabelle ein, d.h. beim Löschen
(delete), Hinzufügen (insert) und Modifizieren (update).
Zeitereignisse
Ein Zeitereignis tritt bei Erreichen eines Zeitpunktes ein. Zeitereignissse können in drei Formen spezifiziert werden:
• Ein absolutes Zeitereignis tritt nur einmal an einem eindeutig definierten Zeitpunkt ein, z.B. ,,Am 31.08.2002 um 14:55 Uhr”.
• Ein periodisches Zeitereignis tritt in regelmäßigen Zeitabständen wiederholt ein, z.B. ,,Jeden Mittwoch um 10:00 Uhr”.
• Ein relatives Zeitereignis ist eine Kombination aus einem absoluten
bzw. periodischen Zeitereignis mit einer Zeitdauer, z.B. ,,Ein Tag vor dem
Semesterende” oder ,,Am dritten Arbeitstag jedes Monats”.
Bei der Beschreibung von Zeitereignissen stößt man unweigerlich auf den Begriff
,,Aktives Echzeit-Datenbanksystem (Aktive Real Time DBS)”, das unten kurz
beschrieben wird.
Ein Computersystem heißt Echtzeitsystem (Real Time System, RTS), wenn
das System ein korrektes Ergebnis nur innerhalb eines bestimmten Zeitintervalls produziert. Außerhalb dieses Zeitintervalls gibt das RTS bestenfalls kein
Ergebnis zurück. Ein aktives Datenbanksystem, das die ,,Echtzeit”-Eigenschaft
erweist, wird aktives Echtzeit-Datenbanksystem (Aktive Real Time Database
System, ARTDBS) genannt. Zeitereignisse sind die wichtigsten Aspekte eines
ARTDBS. In einem ARTDBS soll genau beobachtet werden, wann ein Zeitereignis eintritt und wie lange dessen Bearbeitung dauert. Die Genauigkeit (die
Granularität) der Zeitmessung hängt von dem jeweiligen System (Computer
bzw. Netz) ab. Als Granularität, der kleinsten Zeiteinheit in einem ARTDBS,
wird normalerweise eine ,,Minute” genommen.
Die Syntax einer aktiven Regel in einem ARTDBS kann wie folgt aussehen4 :
3
4
Operationen aus Ereignisalgebra: OR, AND, NOT, Sequenz
Vgl. [AKPat21], S410
10
KAPITEL 2. GRUNDLAGEN VON DATENBANKEN
ON event E
IF condition C
DO <COMPLETE> action A <WITHIN t seconds>
Es gibt noch Fragen, die durch die Semantik beantwortet werden müssen.
Eine Regel R1 in einem ARTDBS könnte z.B. wie folgt aussehen:
ON 31.08.2002 14:55
IF Bedingung C1
DO Aktion A1 innerhalb von 5 Minuten.
Die erlaubte Zeitdauer ist bei diesem Beispiel (R1 ) im Aktionsteil festgeschrieben. Die Semantik einer derartigen Regel könnte z.B. folgendermaßen lauten:
Falls die Bedingung C1 am 31.08.2002 um 14:55 Uhr (t:=31.08.2002 14:55) gilt
(erfüllt ist), soll die Aktion A1 ausgeführt werden und muss innerhalb von 5
Minuten (bis zum 31.08.2002 um 15:00 Uhr [oder bis t+5 Minute]) abgearbeitet
sein. Im Bild 2.2 wurde die Bearbeitung dieser Regel bezüglich einer Zeitachse
geschildert.
31.08.2002 14:55
31.08.2002 15:00
Zeit / Minute
Bearbeitungsanfang
Obergrenze für
die Bearbeitung
Abbildung 2.2: Zeitgrenze von 5 Minute
Betrachten wir nun die Regel R2 mit einer anderen Syntax:
ON t in [31.08.2002 14:55, 31.08.2002 15:30]
IF Bedingung C2
DO Aktion A2.
Die Ausführung von A2 wird angefangen, wenn die Bedingung C2 innerhalb
des Zeitintervalls ,,[31.08.2002 14:55, 31.08.2002 15:30]” erfüllt ist. Der Unterschied zwischen R1 und R2 zeigt sich, wenn das System den Eintritt des Zeitereignisses nicht direkt am 31.08.2002 um 14:55 Uhr, sondern (Sekunden bzw.
Minuten) später meldet. In einer solchen Situation beginnt das System beide
2.2. TRIGGER IN SQL3
11
Aktionen auszuführen (unter Annahme, dass beide Bedingungen erfüllt sind).
Die Ausführung der Aktion der ersten Regel (R1 .A1 ) gibt kein (korrektes) Ergebnis, falls die Ausführung über die (Zeit-) Obergrenze hinaus geht. Die Aktion
der zweiten Regel (R2 .A2 ) wird vollständig ausgeführt, ohne die (Zeit-) Obergrenze zu beachten.
Wenn diese Regeln (R1 , R2 ) direkt am ,,[31.08.2002 14:55, 31.08.2002 14:55]”
gefeuert werden und das System mit der Bearbeitung bis ,,[31.08.2002 14:55,
31.08.2002 15:30]” fertig ist, so haben beide Regeln dieselbe Wirkung. Das folgende Beispiel, Regel R3 , kombiniert die jeweilige Syntax der beiden oben angegebenen Regeln:
ON t in [31.08.2002 14:55, 31.08.2002 15:30]
IF Bedingung C3
DO Aktion A3 innerhalb von 5 Minuten.
Diese Regel darf innerhalb des Zeitintervalls [31.08.2002 14:55, 31.08.2002 15:30]
gefeuert werden. Wenn C3 erfüllt ist, soll die Bearbeitung von A3 innerhalb 5
Minuten (t+5 Minute) fertig sein5 .
2.2
Trigger in SQL3
SQL, Structure Query Language, ist eine weit verbreitete Sprache zur Definition und Manipulation von relationalen Datenbanken. Die erste standardisierte
Version (SQL-86) wurde im Jahre 1986 realisiert und die aktuellste standardisierte Version von SQL ist SQL3. Der Einsatz der Spracherweiterung um die
Triggerfunktionalität wurde zum ersten Mal in SQL3 vorgesehen, obwohl die
Triggerfunktionalität bei manchen SQL2-Implementierungen schon bereits unterstützt wurde. Ein Trigger ist in SQL3 eine (mit einem eindeutigen Namen)
gekennzeichnete ECA-Regel. Ein SQL3-Trigger besteht aus folgenden Komponenten: einer Tabelle, dem Datenmanipulationsbefehl (DML-Operation), einer
Bedingung und einer Aktion. Ein Trigger wird in SQL3 explizit durch den Befehl
,,CREATE TRIGGER” definiert.
2.2.1
Syntax von SQL3-Triggersprache
Die Syntax für die Trigger-Definition in SQL3 sieht wie folgt aus:
<trigger definition> ::=
CREATE TRIGGER <trigger name>
5
In der vorliegenden Arbeit werden Zeitereignisse der Form von R2 unterstützt.
12
KAPITEL 2. GRUNDLAGEN VON DATENBANKEN
<trigger action time> <trigger event>
ON <table name> [ REFERENCING <old new values alias list>]
<triggered action>
<trigger action time> ::=
BEFORE
| AFTER
<trigger event> ::=
INSERT
| DELETE
| UPDATE [ OF <trigger column list> ]
<trigger column list> ::= <column name list>
<triggered action> ::=
[ FOR EACH { ROW | STATEMENT }]
[ WHEN <left paren> <search condition> <right paren>]
<triggered SQL statement>
<triggered SQL statement> ::=
<SQL procedure statement>
| BEGIN ATOMIC
{ <SQL procedure statement> <semicolon> }...
END
<old or new values alias list> ::=
<old or new values alias>...
<old new values alias> ::=
OLD [ROW] [AS] <old values correlation name>
| NEW [ROW] [AS] <new values correlation name>
| OLD TABLE [AS] <old values table alias>
| NEW TABLE [AS] <new values table alias>
<old values table alias> ::=<identifier>
<new values table alias> ::=<identifier>
<old values correlation name> ::= <correlation name>
2.2. TRIGGER IN SQL3
13
<new values correlation name> ::= <correlation name>
Dabei bedeuten die Parameter wie folgt:
<column name list> ist eine Liste bestehend aus Spaltennamen der betroffenen
Tabelle. In der Liste darf keine Spalte doppelt oder gar mehrfach vorkommen.
<left paren> <search condition> <right paren>: Mit Diesem Ausdruck wird
eine Bedingung formuliert. Der linke und rechte Teil können Parameter oder
Konstanten sein, die durch den Vergleichsoperator (<search condition>) miteinander verglichen werden.
<SQL procedure statement> ist ein SQL-Ausdruck.
<identifier>’s sind eindeutige Namen für den alten bzw. neuen Zustand der
betroffene Tabelle.
<correlation name> sind eindeutige Namen für den alten bzw. neuen Zustand
der betroffene Zeilen.
2.2.2
Semantik von SQL3-Triggersprache
Ein SQL-Ausdruck kann mehrere Trigger feuern. Die gefeuerten Trigger sind
entweder Before- oder Aftertrigger. Zusätzlich kann ein Trigger ein ROW-Level
(FOR EACH ROW) oder ein STATEMENT-Level (FOR EACH STATEMENT)
sein. Als ein wichtiger Punkt ist bei der Triggerbearbeitung zu beachten:
Ein Beforetrigger darf keine weiteren Trigger feuern, d.h. wenn die
Bedingung eines gefeuerten Beforetriggers erfüllt ist, soll die Aktion
des Triggers direkt ausgeführt werden, ohne darauf zu achten, ob
durch die Ausführung weitere Trigger gefeuert werden könnten.
Die Semantik der Triggerbearbeitung in SQL3 ist wie folgt:
1. Der SQL-Ausdruck ,,Si ” soll ausgeführt werden. Tritt ein Datenbankereignis E aufgrund der Ausführung dieses SQL-Ausdruck ,,Si ” ein , so werden
an dieser Stelle drei Parameter berechnet:
(a) die Menge der Beforetrigger BTrs, die durch E gefeuert werden,
(b) die Menge der Aftertrigger ATrs, die durch E gefeuert werden,
(c) den sogenannten ,,Trigger Execution Context” (T ECi ), der aus folgenden Teilen besteht :
• dem Namen der betroffenen Tabelle,
• dem Datenmanipulationsbefehl (DELETE, INSERT oder UPDATE),
• einer Menge von Transitionen bestehend aus zwei temporären
Tabellen:
14
KAPITEL 2. GRUNDLAGEN VON DATENBANKEN
i. OLD TABLE beinhaltet die alten Werte der Betroffenen Zeilen (vor der Ausführung des SQL-Befehls),
ii. NEW TABLE beinhaltet die neuen Werte der Betroffenen
Zeilen (nach der Ausführung des SQL-Befehls).
2. Ist die Menge der Transitionen leer (keine Datenänderung), sollen alle
ROW-level Trigger aus der Menge der Beforetrigger ,,BTrs” entfernt werden.
3. Die Trigger in der Menge BTrs werden nach dem Erzeugungsdatum sortiert. Nach dem Sortieren der ,,BTrs” wird jeder Trigger ,,Tr” aus dieser
Menge wie folgt bearbeitet:
• Ist ,,Tr” ein STATEMENT-Level Trigger, so wird die Tr.Condition
ausgewertet. Ist das Ergebnis = ,,True”, wird jedes STATEMENT
der Tr.Action ausgeführt.
• Ist ,,Tr” ein LOW-Level Trigger, so wird für jede Transition:
die Tr.Condition ausgewertet. Gibt die Auswertung ,,True” zurück,
wird jedes STATEMENT von Tr.Action ausgeführt.
4. An dieser Stelle wird der SQL Ausdruck ,,Si ” ausgeführt.
5. Die Integrität der Datenbank wird hier getestet und ggf. die Folgeänderungen vorgenommen6 .
6. Ist die Menge der Transitionen leer (keine Datenänderung), werden alle
ROW-level Trigger aus der Menge Aftertrigger ,,ATrs” entfernt.
7. Trigger in der Menge ATrs werden nach dem Erzeugungsdatum sortiert.
Nach dem Sortieren der ,,ATrs” wird jeder Trigger ,,Tr” aus dieser Menge
wie folgt bearbeitet:
• Ist ,,Tr” ein STATEMENT-Level Trigger, so wird die Tr.Condition
ausgewertet. Ist das Ergebnis der Auswertung = ,,True”, wird jedes
STATEMENT der Tr.Action als neue Eingabe ,,Sj ” an den Schritt
(1.) weitergegeben.
• Ist ,,Tr” ein LOW-Level Trigger, so wird für jede Transition:
die Tr.Condition ausgewertet. Gibt die Auswertung ,,True” zurück,
wird die Ausführung jedes STATEMENTs ,,Sj ” von Tr.Action an
dem Schritt (1.) weiter durchgeführt.
6
Vgl. [AKPat10], [SQLMeSi], [SQLStnd], [SQLTrKo]
2.2. TRIGGER IN SQL3
15
Vor der Auswertung einer Triggerbedingung sowie vor der Bestimmung eines
neuen SQL-Befehls aus der Triggeraktion sollen die Parameter (OLD TABLE,
NEW TABLE, OLD ROW und NEW ROW) aus der Menge der Transitionen
berechnet und in Triggerbedingungen bzw. in Triggeraktionen eingesetzt werden.
16
KAPITEL 2. GRUNDLAGEN VON DATENBANKEN
Kapitel 3
Visual Basic for Applications
In diesem Kapitel wird die Programmiersprache ,,Visual Basic for Applications”
(VBA) beschrieben. VBA ist wie jede andere gut entwickelte Programmiersprache sehr umfangreich und deswegen in einem Kapitel dieser Arbeit nicht
vollständig darzustellen. In diesem Kapitel wird eine kurze Einführung in diese
Programmiersprache gegeben. VBA wird in dem Umfang beschrieben, wie es
zum Verständnis der Arbeit erforderlich ist1 . VBA ist ein Dialekt der Programmiersprache Basic und hat viele Gemeinsamkeiten mit der Programmiersprache
Visual Basic(VB), die selbst ein Dialekt von Basic ist. VBA ist keine eigenständige Programmiersprache, d.h. ein VBA-Programm ist an das Anwendungsprogramm gebunden, in dem es entwickelt wurde. Ursprünglich wurde VBA dazu konzipiert, als Makroprogrammiersprache in MS-Office-Komponenten eingesetzt zu werden. Anwendungen werden unter MS-Office-Komponenten vor allem
in MS-Access und MS-Excel mit VBA programmiert. Es existieren keine grundlegenden Unterschiede zwischen VB und VBA. Jedoch liegt ein wesentlicher Unterschied darin, dass die VBA-Programme direkt an MS-Office-Komponenten
gebunden sind und alleine nicht existieren können. Wenn auch VBA eine weitaus
größere Anwendungslandschaft innehat, wird an dieser Stelle nur von VBA in
Verbindung mit Access die Rede sein, da in dieser Arbeit der Einsatz der VBA
in Access im Vordergrund steht. Mit Hilfe der VBA-Befehle können Access
Komponenten und ihr Verhalten kontrolliert werden. Dies kommt vor allem bei
Formularereignissen in Form der ,,Code behind Forms” vor, in denen der VBACode vollständig mit dem Formular verbunden ist.
1
Ausführlich wurde VBA vor allem in [A00AN], [A00BK], [A97AN], [A0SQLBB] und
[VB6Ko] beschrieben.
17
18
3.1
KAPITEL 3. VISUAL BASIC FOR APPLICATIONS
Sprachgrundlagen
Variablen sind die Elemente, die in einem Programm vorübergehend Inhalte
bekommen und genutzt werden, um Berechnungen in dem Programm durchzuführen. Variablen sollen vor ihrer Verwendung deklariert werden, d.h. der
Kompiler soll über ihrer Existenz informiert werden. In VBA können die Variablen auf zwei verschiedene Arten deklariert werden: die implizite und die
explizite Art der Deklaration. Bei der impliziten Deklaration werden die Variablen direkt und automatisch durch deren erste Anwendung im Programm
deklariert. Bei expliziten Deklarationen müssen Variablen zusätzlich vor deren
ersten Anwendung deklariert werden.
Mit dem Befehl ,,Dim Variablename [As typ]” erfolgt die Deklaration einer Variablen mit dem Namen Variblename vom Datentyp typ. Im Buch
[A00AN] wird empfohlen, die Variablen bereits vor der ersten Anwendung zu
deklarieren. Indem der Ausdruck ,,option Explicit” am Anfang des Codes
eingesetzt wird, kann der Programmierer zur Deklaration der Variablen vor deren ersten Anwendung gezwungen werden. Wird dieser Befehl am Anfang eines
jeden Codes hinzugefügt, so wird der VBA-Kompiler benachrichtigt: Jede Variable muss vor dem ersten Gebrauch in diesem Code deklariert werden. Beim
Erzeugen neuer Codes, wird dann der Befehl Option Explicit am Anfang des
Codes automatisch hinzugefügt, wenn der dafür vorgesehene Eintrag im VBAFenster [Extras → Optionen → Editor → Code-Einstellung (Variablendeklaration erforderlich)] markiert wird.
Der Datentyp einer Variablen gibt an, welche Art von Inhalten dieser Variable zugewiesen werden dürfen. Der Datentyp kann eine Zahl, eine Zeichenfolge,
ein Datum, etc. bezeichnen. Wird bei der Deklaration einer Variable kein Datentyp angegeben, so ist der Datentyp standardmäßig Variant. Variant kann jede
Art von Inhalten speichern. Folgende Datentypen können zur Deklaration einer
Variablen verwendet werden: Byte, Boolean, Integer, Long, Single, Double, Currency, Decimal, Date, Object, String, Variant(mit Zahlen), benutzerdefinierter
Datentyp.
Konstanten sind Variablen, deren Inhalte nicht veränderbar sind. Die Inhalte von Konstanten werden in einem Programm nur bei der Deklaration zugewiesen. Konstanten beinhalten in der Regel bestimmte globale Größen. Solche
Größen werden häufig im Programm und zwar in verschiedenen Modulen und
Klassenmodulen gebraucht und verwendet. Die manuellen Änderungen einer
3.1. SPRACHGRUNDLAGEN
19
Konstanten, d.h. die Änderung der Zeile, in der diese Konstante deklariert wurde, kann eine Änderung an allen Stellen verursachen, in denen diese Konstante
angewendet wurde.
Der Gültigkeitsbereich von Variablen wird durch die Schlüsselwörter
Private, Public und Static definiert, z.B. ,,Private strPrivaterText As String”,
,,Public strGlobalerText As String”, ,,Static strStatistigerText As String”. Eine
in einer Prozedur deklarierte Variable ist nur innerhalb dieser Prozedur gültig.
Eine Variable darf nur innerhalb einer Prozedur als Static deklariert werden,
und sie behält ihren Inhalt auch nach dem Ende der Prozedurausführung. Eine
Variable darf nur am Anfang eines Moduls bzw. Klassenmoduls als Private oder
Public deklariert werden. Als Private deklarierte Variablen haben ihre Gültigkeit nur innerhalb eines Moduls bzw. innerhalb eines Klassenmoduls. Sie dürfen
von jeder Prozedur in diesem Modul bzw. in diesem Klassenmodul angewendet
werden. Die als Public deklarierten Variablen sind von jeder Komponente in
Access nutzbar.
In VBA existieren zwei Arten von Prozeduren, Sub und Function. Beide
können als Public, Private oder/und Static deklariert werden. Diese Prozeduren
lassen sich wie folgt definieren:
[Private | Public] [Static] Sub name([Argumentliste])
[Anweisungen]
[Exit Sub]
[Anweisungen]
End Sub
[Private | Public][Static]Function name([Argumentliste])[As Typ]
[Anweisungen]
[name=Ausdruck]
[Exit Function]
[Anweisungen]
[name=Ausdruck]
End Funktion
Die Argumentliste beinhaltet Variablen, die an die Prozedur übergeben werden. Die Variablen der Argumentliste werden genauso deklariert, wie sie in einem Modul oder Klassenmodul deklariert werden. Diese Variablen werden mit
Kommata voneinander getrennt. In dem folgenden Beispiel wurde eine SubProzedur ,,Test” mit vier Eingabe-Parametern definiert.
20
KAPITEL 3. VISUAL BASIC FOR APPLICATIONS
public Sub Test(ByVal dbl als Double, _
ByRef str as Sting, _
int as Integer_
var)
Anweisungen
End Sub
Im Beispiel wurden auch neue Begriffe verwendet: ByVal und ByRef. Innerhalb der Prozedur ,,Test” können die Variablen dbl, str, int und var verwendet
werden, dabei dürfen auch die Inhalte dieser Variablen geändert werden. Wenn
die Variablen als ByRef deklariert sind, werden die Variablenänderungen nach
der vollständigen Prozedurausführung an das aufrufenden Programm weitergeleitet. Alle Variablen, die als ByVal deklariert sind, behalten ihre ursprünglichen Inhalte. Die Standardeinstellung bei der Deklaration einer Variablen in der
Argumentliste ist ByRef. Im Beispiel werden die Variablen int und var standardmäßig als Reference an die Prozedur übergeben. Es wird empfohlen die
Übergabevariablen immer als ByVal zu deklarieren, damit die Werte nicht versehentlich geändert werden. Die Zeilen werden in VBA mit einem Hochkomma
am Anfang jeder Zeile als Kommentar bezeichnet, und werden vom Kompiler ignoriert. Weitere Ausführungen zu den grundlegenden Sprachelementen von
VBA, z.B. IF-Anweisungen, Schleifen, Sprungbefehle, etc. finden sich in der o.a.
Literatur.
3.2
Module, Klassenmodule und Objekte
Es lässt sich darüber streiten, ob VBA eine Objektorientierte Programmiersprache ist oder nicht. Aus der Sicht einer traditionellen, rein prozeduralen Sprache
wie c ist VBA als eine objektorientierte Programmiersprache einzustufen. Aus
der Sicht einer objektorientierten Sprache wie c++ oder Java ist VBA als eine
nicht vollständig objektorientierte Programmiersprache anzusehen, da beispielsweise die Vererbung in VBA nicht existiert. In VBA sind Objekte wie in jeder
objektorientierten Programmiersprache beteiligt.
Objekte:
Im allgemeinen ist ein Objekt in VBA ein programmierbares Element. Formulare, Tabellen, Berichte und sogar auch die in Formularen vorhandenen Kontrollelemente, werden in VBA als Objekte bezeichnet. Ein Objekt ist eine Sammlung
von Eigenschaften und Methoden. Eigenschaften sind in diesem Sinne die Attribute eines Objektes, die das Verhalten dieses Objektes beeinflussen. Zum Beispiel ist die Hintergrundfarbe eines Formulars eine Eigenschaft dieses Objektes.
3.2. MODULE, KLASSENMODULE UND OBJEKTE
21
Eine (Objekt)Methode ist eine Funktion, die im Objekt eingebaut ist und eine
bestimmte Aufgabe erledigt, z.B. die Prozedur ,,Private Sub Form Open(Cancel
As Integer)” wird innerhalb eines Formular-Klassenmoduls eingesetzt und programmiert. Diese Prozedur wird später beim Öffnen des Formulars ausgeführt.
Die Eigenschaften und Methoden können als Private oder Public definiert sein.
Die als Private deklarierten Eigenschaften bzw. Methoden dürfen nur von Methoden benutzt werden, die in demselben Objekt definiert sind. Die hingegen
als Public definierten Methoden können überall dort aufgerufen werden, wo das
Objekt angewendet wird. Es gibt in VBA unter Access zwei verschiedene Objektarten. Zum einen gibt es die Access-Objekte (die Access-Komponenten),
zum anderen Objekte, die vom Programmierer erzeugt werden können. Die
Access-Objekte stehen in einer Hierarchie auf verschiedenen Stufen: Die AccessObjekthierarchie wurde in dem Buch [A00AN] im Kapitel 9 geschildert und
ausführlich beschrieben.
Was aber in ARTA eine wichtige Rolle spielt, ist der Begriff ,,Auflistung”. Eine Auflistung in der Access-Hierarchie ist eine Menge von Objekten des gleichen
Typs. Diese Objekte sind in der Auflistung in einer vorbestimmten Reihenfolge
zusammengefasst. Eine Auflistung kann in einer Schleife ,,durchlaufen” werden.
Beim ,,Durchlaufen einer Auflistung” wird auf jedes Objekt und dessen Eigenschaften und Methoden zugegriffen. Zum Beispiel enthält die Auflistung Forms
alle Formulare, die in einer Access-Datenbank vorhanden sind. Die Auflistung
Controls enthält alle Steuerelemente eines Formulars oder eines Berichts. In dem
folgenden Beispiel2 durchläuft eine Prozedur (,,AlleOffenenFormulare”) die Auflistung ,,Forms” und gibt die Namen aller Formulare in dieser Auflistung aus.
Dann wird die Auflistung Controls jedes Formulars durchlaufen und die Namen
aller auf dem Formular befindlichen Steuerelemente ausgegeben.
In dem Beispiel sind auch Teile der Objekthierarchie angegeben:
Forms → {Form1 , Form2 , . . . } und Formn → {Control1 , Control2 , . . . } mit
n∈ {1, 2, . . . }. Außer der in Access existierenden Auflistungen können auch
benutzerdefinierte Auflistungen erzeugt und programmiert werden, die AccessKomponenten bzw. benutzerdefinierte Objekte beinhalten können. In VBA besteht ebenfalls die Möglichkeit, Objekte zu programmieren, die in solchen Auflistungen zusammengefasst werden. Klassenmodule spielen in diesem Zusammenhang eine wichtige Rolle. Aus diesem Grund werden im folgenden Klassenmodule und deren enge Verwandte ,,Module” gesondert beschrieben. Eine Prozedur
wird in VBA innerhalb einer Umgebung definiert. Diese Umgebung kann ein
Modul oder ein Klassenmodul sein.
2
Das Beispiel ist aus der Online-Hilfe von Access 2000 übernommen.
22
KAPITEL 3. VISUAL BASIC FOR APPLICATIONS
Sub AlleOffenenFormulare()
Dim frm As Form, ctl As Control
’ Forms-Auflistung durchlaufen.
For Each frm In Forms
’ Name des Formulars ausgeben.
Debug.Print frm.Name
’ Controls-Auflistung jedes Formulars durchlaufen.
For Each ctl In frm.Controls
’ Namen der Steuerelemente ausgeben.
Debug.Print ">>>"; ctl.Name
Next ctl
Next frm
End Sub
Ein Modul ist eine Sammlung von Prozeduren. Module lassen sich als Werkzeug von anderen Objekten nutzen. In einem Modul dürfen Prozeduren als Privat oder Public definiert werden. Die als Private definierten Prozeduren können
nur den im selben Modul existierenden Prozeduren als Hilfsfunktionen dienen.
Die in einem Modul als Public definierten Prozeduren können von Funktionen
in anderen Modulen oder Objekten aufgerufen werden. Ein Modul erzeugt man,
indem man mit der Maus im VBA-Fenster (auf Einfügen → Modul) anklickt.
Ein Modul muss unter einem eindeutigen Namen in der Access-Datenbank gespeichert werden.
Klassenmodule sind im Gegensatz zu Modulen umfangreicher, da sie mehr
Funktionalitäten beinhalten. Ein Klassenmodul wird durch Mausklick (auf Einfügen → Klassenmodul) erzeugt und muss unter einen eindeutigen Namen gespeichert werden. Klassenmodule sind die eigenständigen Objektklassen, aus denen Objekte instantiieren können. Objektorientiertes Programmieren in VBA
setzt den Einsatz von Klassenmodulen zugrunde. In einem Klassenmodul werden Eigenschaften, Methoden und Variablen definiert, bzw. programmiert. Die
in einem Klassenmodul definierten Variablen dienen dem Programmierer später
als Speicherbehälter. Die Datenkapselung in VBA wird unterstützt, indem Objektvariablen nur durch Methoden verändert werden. In einer Auflistung können
auf Methoden und Eigenschaften jedes Elementes zugegriffen werden. Dadurch
werden die Methoden der Unterklasse (Objekte dieser Auflistung) in der Oberklasse (Auflistung) zur Verfügung gestellt.
Auf Eigenschaften eines Objektes wird in der Regel nicht direkt zugegriffen, wenn dies auch für globale Variablen prinzipiell möglich ist, sondern mit
3.3. API
23
Hilfe der als Public definierten Methoden. VBA stellt dafür eine Methode zur
Verfügung: den Einsatz der Property-Routinen3 (Property Get, Property
Let und Property Set) in Klassenmodulen. Die Eigenschaften (Variablen)
eines Klassenmoduls werden als ,,Private” deklariert; Mit Hilfe von PropertyRoutinen werden Inhalte dieser Eigenschaften modifiziert oder abgelesen.
Property-Routinen haben zwei grundlegende Vorteile.
1. Es kann programmiert werden, welcher Inhalt einer Eigenschaft zugewiesen werden darf.
2. Gleichzeitig können bei der Zuweisung bestimmte Aufgaben erledigt werden. (Diese Können z.B. direkten Einfluss auf andere Variablen nehmen.)
Angenommen, ein Klassenmodul wird mit dem Namen ,,clsTest” definiert, so
wird mit dem Befehl ,,Dim objTest As New clsTest” eine Instanz (ein neues
Objekt) zu dieser Klasse erzeugt. Auf die Eigenschaften und Methoden dieses
Objektes wird mit
objTest< .|! >EigenschaftOderMethode
zugegriffen. Auflistungen werden in Form von Klassenmodul programmiert.
Eine Auflistung soll die notwendigen Methoden und Eigenschaften beinhalten.
Zusätzlich braucht eine Auflistung eine Variable vom Typ ,,Collection”, in die
Objekte gespeichert werden können. Mit Hilfe der Methode ,,Add” können Elemente in die Auflistung aufgenommen werden. Die Methode ,,Remove” hilft
Elemente aus der Auflistung zu entfernen. Mit Hilfe der Befehle, Item, Count,
BOL, EOL, MoveFirst, MoveLast, MoveNext, MovePrev kann die Auflistung
durchlaufen und auf Elemente der Auflistung zugegriffen werden. Diese Methoden können beliebige Namen tragen und o.a. Namen sind nur als Vorschläge
gedacht. Vorausgesetzt, es wurde eine Auflistung objColl von Objekten der
Klasse clsTest definiert, so können auf die Eigenschaften bzw. Methoden des
ersten Elements dieser Auflistung mit
objColl.Item(0).EigenschaftOderMethode
zugeriffen werden. Durch das ”Durchlaufen” einer Auflistung sind alle ihre Objekte erreichbar. Das Durchlaufen einer Auflistung kann mittels verschiedener
Methoden durchgeführt werden. In [A00AN] sind diese und weitere Hinweise
bereits ausführlich erläutert worden.
3.3
API
In diesem Abschnitt soll eine Technik vorgestellt werden, die im ARTA für die
Realisierung von Timern benutzt wird.
3
Ausführliche Erläuterungen dazu enthält [A00AN].
24
KAPITEL 3. VISUAL BASIC FOR APPLICATIONS
API (Application Programming Interface) ist eine Software-Schnittstelle, die
dem Programmierer ermöglicht Windows Funktionalitäten in seinem Programm
zu nutzen. Diese Funktionalitäten können praktisch alles darstellen, was in einem Windows Betriebsystem abläuft, z.B. Fensterverwaltung, Zeitverwaltung,
Hardwareverwaltung, . . . . Jede Funktion von API ist in einer DLL Datei (,,Dynamic Link Library”), die die Endung ,,.dll’ hat, eingebunden. DLL Dateien sind
in der Regel im Windows Stammverzeichnis gespeichert. Eine DLL-Datei wird
erst dann in den Arbeitsspeicher transportiert, wenn sie tatsächlich benötigt
wird. Die Funktionen einer DLL-Datei können in jedem Programm, das unter
Windows läuft, benutzt werden.
In VBA müssen die Funktionen von API erst deklariert werden, damit sie
aufgerufen werden können. Durch die Deklaration einer API-Funktion wird dem
Programm mitgeteilt, in welcher DLL-Datei diese Funktion zu finden ist, welche
Parameter an diese Funktion übergeben werden und wie die Rückgabe dieser
Funktion aussieht. Die Deklaration einer API-Funktion wird wie folgt durchgeführt:
[Private | Public] Declare [Function | Sub] name Lib filename.dll Alias
newname (ParameterListe) [As Datentyp]
Die Funktionen sind unter dem Windows Betriebsystem je nach Thema und
Funktionalität in verschiedenen DLL-Dateien zusammengefasst. In der Tabelle 3.1 sind die wichtigsten bzw. die am häufigst genutzten DLL-Dateien sowie die in diesen DLL-Dateien behandelten Themenschwerpunkte aufgelistet.
Informationen über eine API-Funktion, wie Funktionsname, ÜbergabeparameDLL-Datei
User32.dll
Kernel32.dll
Gdi32.dll
Advapi32.dll
Wininet.dll
Wsock32.dll
Shell32.dll
Die Themen der Funktionen
Allgemeine Benutzerfunktionen, Nachrichtenverwaltung, Windowselemente, Timer.
Betriebsystembezogene Funktionen wie Speicherhandling, Systeminformationen.
Zeichenwerkzeuge, Gerätekontext bezogene Operationen.
Nutzung der Windows Registry, Nutzerrechte, Sicherheit und EventLogging.
Internet-Funktionen des Internet Explorers.
Netzwerk und rechnerübergreifende Kommunikation.
Dateifunktionen, Dateiicons, starten von Anwendungen, Dateidialoge.
Tabelle 3.1: DLLs und ihre Funktionalitäten
3.3. API
25
ter, Rückgabetyp und Format der Callback-Funktion4 können nicht unmittelbar herausgefunden werden, aber z.B. mittels des Hilfsprogramms ,,WinAPIViewer”. Das Programm wird mit den Microsoft Office 2000 Developer (MOD)
mitgeliefert und kann im VBA-Editor-Fenster über MOD-Add-Ins aufgerufen
werden.
Callback-Funtion:
Manche API-Funktionen setzten die Adresse einer sogenannten Callbackbzw. Rückruf-Funktion als einen ihrer Eingabeparameter voraus. Diese Funktion
wird von der API-Funktion bzw. vom Betriebsystem später automatisch aufgerufen. Die Adresse dieser Funktion wird mit dem Schlüsselwort AddressOf,
gefolgt von dem Rückruf-Funktionsnamen, an die API-Funktion angegeben.
Im folgenden Beispiel ist der Einsatz dieses Schlüsselwortes in der Funktion ,,SetTimer” zu sehen. SetTimer ist eine API-Funktion, die in der Datei
,,User32.dll” abgelegt ist. SetTimer setzt die Adresse einer Rückruf-Funktion
als ihren vierten Parameter voraus. Angenommen, diese Rückruf-Funktion heißt
TimerProc: SetTimer soll dann wie folgt aufgerufen werden
SetTimer hwnd, 12345, 5000, AdressOf TimerProc,
wodurch dann die Funktion TimerProc nach 5000 Millisekunden automatisch
aufgerufen wird. Auf die Funktion ,,SetTimer” und deren Einsatz wird in Kapitel 6 erneut eingegangen.
Rückruf-Funktionen müssen in einem Modul definiert werden, da sie direkt aufgerufen werden; Deswegen können Funktionen in Klassenmodulen und
in Formularen nicht als Rückruf-Funktionen benutzt werden. Bei Rückruf Funktionen muss die Parameterliste exakt mit denen übereinstimmen, die die
Hauptfunktion voraussetzt. Die meisten Rückruf-Funktionen sollten schnellst
-möglich ausgeführt werden, da sonst Access unvorhergesehen abstürzt.
Die Arbeit mit API-Funktionen und besonders mit denen, die eine
Rückruf-Funktionsadresse als Parameter voraussetzten, erfordert genaue Aufmerksamkeit. Access wird bei einer Anomalie sehr schnell
zum Absturz gebracht, auch wenn es sich um eine harmlose Anomalie bei der Anwendung einer API-Funktion handelt.
Weiterführende Literatur zu diesem Thema: [VB6Ko] und [APIHnd].
4
Der Begriff ,,Callback-Funktion” wird gesondert beschrieben
26
KAPITEL 3. VISUAL BASIC FOR APPLICATIONS
3.4
Fehlerbehandlung in VBA
Für ein erfolgreiches Programmieren ist es erforderlich, Fehler am laufenden
Programm zu suchen und zu behandeln. Es gibt grundsätzlich drei verschiedenen
Arten von Fehlern:
Fehler beim Kompilieren treten auf, wenn im Code Befehle falsch geschrieben oder Funktionen falsche Eingabeparameter zugewiesen werden. Diese Funktionen können entweder in VBA vordefiniert oder vom Benutzer vorprogrammiert sein. Beim Kompilieren werden solche Fehler entdeckt und dementsprechend gemeldet. Damit das Programm lauffähig ist, müssen diese Fehler behoben werden. Das Endergebnis wird also nicht fehlerhaft sein, weil die Fehler
bereits vorher entfernt worden sind. In Access existiert eine ,,automatische Syntaxprüfung”, durch die der Programmierer während der Programmeingabe auf
offensichtliche Schreibfehler sofort hingewiesen wird. Die automatische Syntaxprüfung kann im Microsoft Visual Basic Fenster unter [Extras → Optionen →
Editor (Code-Einstellungen)] ein- oder ausgeschaltet werden. Es empfiehlt sich,
die automatische Syntaxprüfung immer einzuschalten, um somit Schreibfehler
zu vermeiden bzw. direkt aufzuspüren und zu beseitigen.
Logische Fehler werden nicht vom Compiler erkannt und daher erst sichtbar, wenn das Programm vollständig ausgeführt wurde. In einer Testphase sollte
ein Programm nach solchen Fehlern durchsucht und gegebenenfalls vor seinem
eigentlichen Einsatz korrigiert werden. VBA stellt Mechanismen sowie Befehle
zur Verfügung, um nach logischen Fehlern zu suchen. Ein in VBA eingesetztes
Werkzeug, das sich für die Fehlersuche als nützlich erweist, ist der ,,Debugger”. Um solche Fehler zu vermeiden ist beim Programmieren ein optimaler
Überblick über den Code notwendig. Dies ist gegeben, wenn Empfehlungen hinsichtlich der Gestaltung eines Programmcodes berücksichtigt werden: Z.B. sollte
ein Programmcode gut kommentiert sein und aus mehreren kleinen Prozeduren
bestehen.5
Laufzeitfehler treten während der Ausführung eines Programms auf. Access meldet solche Fehler durch eine entsprechende Fehlermeldung und beendet das Programm standardmäßig. Laufzeitfehler lassen sich im Code behandeln, wenn Access-VBA entsprechend eingestellt ist. Im Registerdialogfeld
von VBA kann eingestellt werden, wie VBA auf Laufzeitfehler reagieren soll
(Extras → Optionen → Allgemein → Unterbrechen bei Fehlern). Wird der
Eintrag Bei nicht verarbeiteten Fehlern markiert, so reagiert Access nicht auf
5
Vgl. [A00AN], [A00BK], [A97AN].
3.4. FEHLERBEHANDLUNG IN VBA
27
,,behandelte Fehler” und überlässt die Behandlung solcher Fehler den VBABefehlen. Jeder aufgetretene Fehler wird von Access in einem Err-Objekt abgelegt. Von diesem Err-Objekt können anschließend die Eigenschaften des Fehlers
abgelesen werden. Das Err-Objekt beinhaltet Methoden, die zur Fehlerbehandlung eingesetzt werden können.6
Die Behandlung von Laufzeitfehlern wird im Code mit On Error Goto
Label aktiviert. Dadurch wird jeder Laufzeitfehler zwischen On Error Goto
Label und der mit Label markierten Zeile abgefangen. Wie dieser Fehler behandelt werden soll, ist erst ab der Zeile Label vorgegeben. In der Tabelle 3.2 sind
die Befehle aufgelistet, mit deren Hilfe die Fehler in (Access-)VBA behandelt
werden:
Die Fehler in einer Funktion werden an die aufrufende Funktion weitergeleitet. Eine On Error -Fehlerbehandlung gilt für die Prozeduren bzw. Funktionen,
für die sie vereinbart wurden und für alle Unterprogramme, d.h. für alle Prozeduren und Funktionen, die in dem Programm mit der Fehlerbehandlung aufgerufen werden. Das gilt nicht für Programmteile oder Unterprogramme, für die
eine eigene Fehlerbehandlung programmiert wurde. Diese Methode der Fehlerbehandlung wird vorwiegend bei Programmen eingesetzt, in denen Fehler auch
in Unterfunktionen vorkommen können, die dann jedoch die gleiche Wirkung
auf das Gesamtergebnis des Programms haben. Im folgenden ist als Beispiel
eine einfache Fehlerbehandlung in einer Sub-Funktion dargestellt:
Sub Fehlerbehandlung()
On Error GoTo FB_Error
Anweisungen
FB_Exit:
Exit Sub
FB_Error:
Die Fehlerbehandlung passiert hier!
Resume FB_Exit
End Sub
Bei Eintritt eines Laufzeitfehlers wird die Ausführung des Programms an die
Zeile FB Error weitergeleitet, in der die eigentliche Fehlerbehandlung durchgeführt wird. Nach der Fehlerbehandlung wird die Ausführung des Programm
6
Vgl. [A00AN], S.233
28
KAPITEL 3. VISUAL BASIC FOR APPLICATIONS
Fehlerbehandlung weiterleiten
On Error Goto Label
On Error Resume Next
On Error Goto 0
Verhalten nach
Fehlerbehandlung
Resume
Resume Next
Resume Label
der
Beschreibung
Die Fehlerbehandlung wird mit diesem Befehl an die Zeile mit der Sprungmarke bzw.
mit der Zeilennummer Label weitergeleitet.
Beim Eintritt eines Fehlers ignoriert das
Programm die Ausführung der fehlerhaften Zeile und macht mit der nächsten Zeile
weiter. Deswegen wird das Programm beim
Eintritt eines Fehlers nicht angehalten!
Mit diesem Befehl wird die Fehlerbehandlung wieder an Access zurückgegeben, d.h.
nach diesem Befehl hält das Auftreten eines Fehlers die Programmausführung an.
Beschreibung
Nach der Fehlerbehandlung beginnt die
Ausführung des Programms von der Zeile
an, in der der Fehler aufgetreten ist.
Nach der Fehlerbehandlung wird das Programm von der Zeile weiter ausgeführt, die
der fehlerhaften Zeile unmittelbar folgt.
Nachdem der Fehler behandelt wurde, wird
das Programm von der Zeile Label weiter
ausgeführt.
Tabelle 3.2: Befehle zur Fehlerbehandlung in VBA
3.5. TRANSAKTIONEN IN VBA
29
an die Zeile FB Exit weitergeleitet, in der eine ordnungsgemäße Beendigung des
Programms mit dem Befehl Exit Sub gewährleistet ist.7
3.5
Transaktionen in VBA
Mehrere Datenbankoperationen können in Access zu einer Transaktion zusammengefasst werden. Das Zusammenfassen einer Anzahl von Datenbankänderungen zu einer Transaktion gewährleistet, dass entweder alle Änderungen vorgenommen werden oder überhaupt keine. Bei der Ausführung von Datenbankänderungen in einer Transaktion muss die Einhaltung der ACID8 -Eigenschaften vom
Datenbankmanagementsystem garantiert werden. Bei einer Aktionsabfrage kann
eingestellt werden, ob die Änderungen, die von dieser Abfrage vorgenommen
werden, in einer Transaktion zusammengefasst werden sollen. Im VBA-Code
wird allerdings eine andere Methode angewendet, um Transaktionen zu erzeugen
und zu verwalten. In VBA steht das DAO9 -Workspace-Objekt mit seinen Methoden für die Transaktionsverwaltung zur Verfügung. Das Workspace-Objekt
enthält drei Methoden zur Transaktionsverwaltung:
• BeginTrans informiert Access, dass eine Transaktion begonnen wurde.
Von da an werden alle Änderungen zwischengespeichert.
• ComitTrans schließt die Transaktion ab, dabei werden alle Änderungen
festgeschrieben.
• Rollback setzt alle Änderungen zurück, die innerhalb dieser Transaktion
vorgenommen wurden.
In einem Access-VBA-Code können bis zu fünf Transaktionen ineinander verschachtelt werden. Abschließend wird im folgenden Beispiel dargestellt, wie eine
Transaktion im Code verwaltet wird.10
7
Vgl. [A00AN], [A00BK], [A97AN].
Atomicity Consistency Isolation Durability: s. [ISKeEi], [ISVrl],[ISVos]
9
Vgl. Abschnitt 4.3
10
Vgl. [A00AN], [A00BK] und [A97AN]
8
30
KAPITEL 3. VISUAL BASIC FOR APPLICATIONS
Sub TransAktion()
Dim wksp As DAO.Workspace
Set wksp = DBEngine.Workspaces(0)
wksp.BeginTrans
If (Erfolgreiches Datenbank-Update) THEN
wksp.CommitTrans
Else
wksp.Rollback
End If
End Sub
Kapitel 4
MS-Access
,,Access” ist in der ersten Version 1.0 im Jahre 1993 auf den Markt gekommen.
Diese Version hatte wenige Assistenten und erfüllte trotzdem grundlegende Anforderungen eines Datenbankmanagmentsystems für PC’s. Diese Version und
die nachfolgenden Versionen 1.1 und 2.0 waren 16-Bit Anwendungen und wurden vor allem mit den Betriebsystemen Windows 3.1 und 3.11 eingesetzt. Mit
der nächsten Version ,,7.0” wurde die neue Generation von MS Access, d.h.
32-Bit Anwendung, ins Leben gerufen wurde. Nacheinander wurden mit den
neuen Versionen Mängel und Schwachpunkte beseitigt und neue Komponenten
hinzugefügt, wie z.B. bessere Assistenten.
4.1
Tabellen und Beziehungen
Access ist ein relationales Datenbankmanagementsystem und daher werden in
einer Access-Datenbank die Informationen in Relationen bzw. Tabellen gespeichert. Jede Tabelle besteht aus Spalten, die innerhalb der Tabelle eindeutige
Namen haben. Jede Zeile einer nicht leeren Tabelle ist ein Datensatz. Die Tabellen, Spalten und Zeilen in Access repräsentieren jeweils Relationen, Attribute
und Tupel. Jede Tabelle darf bis zu 255 Spalten (bzw. Felder) haben. Die Feldernamen dürfen aus bis zu 64 Zeichen bestehen. Jeder Spalte kann ein Datentyp
zugeordnet werden und das bedeutet, dass die Einträge in dieser Spalte nur den
angegebenen Datentyp haben dürfen.
Für jede Tabelle kann ein Primärschlüssel bestimmt werden. Der Primär
-schlüssel ist eine Spalte, in der kein Wert mehrfach vorkommen darf. Damit werden die Datensätze (Informationen in Zeilen) eindeutig bestimmt. Der
Primärschlüssel kann entweder manuell erzeugt werden oder automatisch durch
Anweisung an Access. Der automatisch erzeugte Schlüssel ist ein Autowert31
32
KAPITEL 4. MS-ACCESS
Feld, das den Datentyp ,,Long Integer” hat. Ein Feld mit dem Typ ,,Autowert”
erhält bei jedem neuen Datensatz automatisch einen neuen eindeutigen Wert.
Als Primärschlüssel kann auch eine Gruppe von Feldern einer Tabelle gewählt
werden, wobei die Kombination dieser Felder Eindeutigkeit des Datensatzes
gewährleistet.
Beziehungen und Integrität
Beziehungen werden zwischen der Tabellen aufgebaut. Eine Beziehung wird
zwischen zwei Tabellen aufgebaut, indem der Primärschlüssel einer Tabelle mit
einem Feld bzw. einer Menge von Feldern einer anderen Tabelle verbunden wird.
Das Feld bzw. die Menge von Feldern der anderen Tabelle heißen in diesem Falle
,,Fremdschlüssel”. In Access gibt es drei Beziehungstypen:
• 1:1-Beziehung ist die einfachste Art. Dabei existiert für jeden Datensatz
der Quelltabelle genau einen Datensatz in der Zieltabelle.
• 1:n-Beziehung ist die am häufigst eingesetzte Beziehung in Access. Dabei
können zu einem Datensatz in der Quelltabelle mehrere (n) Datensätze
in der Zieltabelle existieren.
• n:m-Beziehung ist eine Beziehung, die angibt, dass ein Datensatz in der
Tabelle 1 n Gegenstücke in der Tabelle 2 hat und ein Datensatz in Tabelle
2 m Gegenstücke in der Tabelle 1 hat. Der Aufbau dieser Beziehung ist
nur mit Hilfe einer Zwischentabelle möglich.
Integrität wird in Access mit Hilfe von zwei Mechanismen unterstützt. Durch
den ersten Mechanismus wird die Gültigkeit eines Datensatzes geprüft, und im
Falle eines Verstoßes gegen die Gültigkeitsregeln wird eine Fehlermeldung ausgegeben und die Datensatzänderung zurückgesetzt. Diese Regeln lassen sich
für eine Tabelle, sowie für einzelne Spalten aufstellen. Der zweite Mechanismus
kommt erst mit dem Aufbau einer Beziehung zustande. Jede Beziehung hat
bestimmte Eigenschaften, die eingestellt werden können. Im Eigenschaftfenster
einer Beziehung werden mehrere Möglichkeiten angeboten, Eigenschaften spezifisch für die Beziehung zu bestimmen. Als eine Eigenschaft einer Beziehung
kann ,,Mit referentieller Integrität” angegeben werden. Dadurch darf ein
neuer Datensatz in einer Tabelle mit einem Fremdschlüssel nicht eingefügt werden, wenn kein entsprechender Wert in der referenzierten Tabelle existiert. Die
referenzierte Tabelle ist die Tabelle, deren Primärschlüssel an der Beziehung
beteiligt ist. Als weitere Eigenschaft einer Beziehung kann auch eingegeben werden, was mit den Datensätzen in einer Tabelle mit Fremdschlüssel passieren soll,
wenn die Werte in der referenzierten Tabelle geändert oder gelöscht werden.
4.2. FORMULARE
33
Abfragen und SQL-Befehle:
Eine Abfrage (View in Access) ist eine Access-Komponente, mit deren Hilfe bestimmte Datensätze aus einer oder mehreren Tabellen ausgewählt werden
können. Mit einer Abfrage ist es auch möglich, die Anzahl einer Datenauswahl,
den Durchschnitt einer Datenauswahl und weitere Details zu bestimmen. Eine
Abfrage in Access ist nicht nur eine Oberfläche, die dem Benutzer bestimmte
Informationen zeigt, die ausgewählten Datensätze einer Abfrage können auch
geändert werden. Je nach Abfragetyp kann die Ausführung der Abfrage bestimmte Aufgaben erledigen. Es existieren in Access verschiedene Abfragetypen:
Auswahlabfrage, Kreuztabellenabfrage, Tabellenerstellungsabfrage, Aktualisierungsabfrage, Anfügeabfrage und Löschabfrage. Welche Aufgaben mit Hilfe welcher Abfragen erledigt werden können, ist aus dem Namen ersichtlich1 . Desweiteren ist noch die Beziehung zwischen Access-Abfragen und SQL zu beleuchten.
Im Hintergrund jeder Abfrage versteckt sich ein SQL-Ausdruck. Bei einer Auswahlabfrage fängt der SQL-Ausdruck z.B. mit ,,SELECT . . . ” an.
QBE steht für Query By Example. Die Abfragen-Entwurfansicht, die Benutzerschittstelle zur Herstellung von Abfragen, wird als QBE bezeichnet. In der
Entwurfansicht einer Abfrage lassen sich jede Art von Abfragen, auch komplizierte, formulieren. Diese Methode hilft vor allem Anfängern, SQL-Ausdrücke zu
formulieren. Auch die Profis werden davon profitieren, weil die SQL-Ausdrücke
sich mit Hilfe von QBE einfach und ohne Schreibfehler formulieren lassen.
4.2
Formulare
Formulare sind Access Komponenten, die als Benutzeroberfläche benutzt werden. Formulare können gebunden oder ungebunden sein. Ein gebundenes Formular unterscheidet sich von einem ungebundenen Formular in der Datenquelle.
Ein Formular kann mit einer Tabelle oder einer Gruppe von Tabellen verknüpft
werden. Die Datensätze der Tabelle können innerhalb des gebundenen Formulars direkt bearbeitet werden. Die Änderungen an Datensätzen innerhalb eines
gebundenen Formulars werden sofort in der Tabelle sichtbar.
Ein ungebundenes Formulars ist mit keiner Tabelle verknüpft, und wird nur
als Oberfläche genutzt. Mit den dafür vorgesehenen Assistenten können Formulare im Access-Hauptfenster erstellt werden. Wie oben bereits erwähnt, ist ein
Formular ein Access-Objekt, das aus mehreren Kontrolelementen (Steuerelementen) bestehen kann. Ein Steuerelement ist selbst ein Access-Objekt, und
kann wiederum aus Unterobjekten bestehen. Bezeichnungsfelder, Textfelder,
Kombinationsfelder, Listenfelder, Optionsfelder, Buttons (Befehlsschaltflächen)
1
Weitere Details über Abfragen in [A00AN], [A00BK] und [A97AN].
34
KAPITEL 4. MS-ACCESS
und etc. sind Steuerelemente, die in ein Formular eingebaut werden können.
Jedes dieser Steuerelemente hat eigene spezielle Funktionalitäten, die in einem
Formular benutzt werden. Z.B. können Buttons dafür eingesetzt werden, um
per Mausklick VBA-Funktionen auszuführen.
Formular-Klassenmodule: Hinter jedem Formular versteckt sich ein Klassenmodul. Dieses Klassenmodul wird gleichzeitig mit dem Formular erstellt und
ist somit ein Teil des Formulars. Was mit dem Formular passiert, wird auch sein
Klassemmodul beeinflussen. Wird z.B. ein Formular gelöscht, wird auch sein
Klassenmudol gelöscht. In einem Formular-Klassenmodul können Funktionen
und Variablen definiert werden. Aus einem Formular kann ein Objekt (eine Instanz) instantiiert werden. Dieses Objekt kann aber nur dann weiter angewendet
werden, wenn erst das zugehörige Formular geöffnet wird. Das Formular kann
entweder einfach per Mausklick geöffnet werden oder innerhalb einer Prozedur
bei der ein Objket vom Formular intantiiert und dessen Eigenschaft Visible auf
True gesetzt wird.
Formular-Ereignisse sind die wichtigsten Eigenschaften von Formularen, die
in einer Access-Anwendung benutzt werden. Auf dem Bild 4.1 ist das Register
des Eigenschaftfensters eines Formulars dargestellt. In einem Formular ist es
möglich einzustellen, dass beim Vorkommen eines bestimmten Ereignisses eine
bestimmte Prozedur ausgeführt wird. Diese Prozedur wird im Klassenmodul
definiert, deren Programmierung dem Benutzer überlassen wird. Die EreignisProzeduren haben vordefinierte Namen. In folgendem Beispiel ist die Prozedur,
die beim Löschen eines Datensatzes ausgeführt wird gezeigt.
Private Sub Form_Delete(Cancel As Integer)
Anweisungen
End Sub.
Nicht nur für ein Formular können Ereignisse definiert und programmiert werden, sonder auch für seine Steurelemente, z.B. die Ausführung einer Prozedur
beim Eintritt des Ereignisses. Die Prozedur im folgenden Beispiel wird beim
Auftritt des Ereignisses ,,Der Mausklick auf dem Button btn EditAction” ausgeführt.
Private Sub btn_EditAction_Click()
Anweisungen
End Sub
4.2. FORMULARE
35
Abbildung 4.1: Formular-Ereignisse
36
4.3
KAPITEL 4. MS-ACCESS
Datenzugriffsobjekte
Jet Database Engine ist der Kern einer Access-Datenbank. Auf alle Daten einer Access-Datenbank können nur mit Hilfe von Jet DB Engine zugegriffen werden. Anforderungen an eine Access-Datenbank muss über diesen Kern
gehen. Dieser Kern steht zwischen den Daten und den übrigen Teilen einer
Access-Datenbank. Im Grunde genommen hat ein Access-Datenbankmanagementsystem alle Funktionalitäten, um eine Datenbank zu verwalten, insbesondere die entsprechende Benutzeroberfläche und die Jet Database Engine. Als
Benutzeroberflächen sind z.B. Formulare, Berichte und Abfragen zu nennen.
Die Aufgabe von Jet DB Engine ist es, die Änderungen, die über eine Benutzeroberfläche vorgenommen werden, an die Datenbank weiterzuleiten. Im Bild
4.2 ist gezeigt, wie die Access-Komponente mit dem Jet DB Engine verbunden
sind. In Access besitzen die Datenzugriffsobjekte eine Hierarchie, deren Spitze
Microsoft Access
MS Access Benutzeroberfläche
MS Access
Applikation
Jet Database Engine
MS Acces
Datenbank
Abbildung 4.2: Access un Jet DB Engine
das Objekt DBEngine ist. DBEngine ist eine Datenbankmaschine und bezeichnet den Jet Database Engine in Access. DBEngine ist keine Auflistung sondern
ein Einzelobjekt. Die Hierarchie wurde im Buch [A00AN] auf Seite 322 geschildert.
DAO oder ADO:
In Access 2000 existieren zwei Datenzugriffsschnitstellen. Die Klassische Datenzugriffsschnitstelle ist DAO (Data Access Objekts). Diese Schnittstelle stellt
4.3. DATENZUGRIFFSOBJEKTE
37
viele Objekte und Methoden zur Verfügung, um auf Daten einer Access Datenbank zuzugreifen. DAO ist für den Zugriff auf relationale Datenbanken vorgesehen. Die zweite Schnittstelle ist ADO (AktiveX Data Objekts). ADO wurde so
entwickelt, um nicht nur auf relationale Datenbanken sondern auch auf anderen Datenquellen zuzugreifen. Mit Access 2000 sollte DAO durch ADO abgelöst
werden. Es ist der Firma Microsoft aber nicht gelungen, alle ADO-Komponente
rechtzeitig fertig zu stellen. Deswegen ist der Einsatz von DAO in einer Access
2000 Datenbank-Anwendung unvermeidbar. DAO ist beim Einsatz in lokalen
Access Datenbanken sehr stabil.
Recordset ist ein häufig eingesetztes Datenzugriffsobjekt. Mit Hilfe von Recordset können die Datensätze einer Tabelle oder einer Abfrage verwaltet werden. In einem Recodset werden die Datensätze einer Tabelle getrennt voneinander zwischengespeichert. Um auf einen Datensatz in einem Recordset zuzugreifen, soll das Objekt ,,Recordset” in einer Schleife durchlaufen werden. Daher
kann zu einem Zeitpunkt nur ein Datensatz zu modifiziert werden. Execute ist
ein Befehl, unter den ein SQL-Ausdruck in VBA ausgeführt wird. Execute ist
eine Methode des Objektes Database. Das folgende Beispiel zeigt den Einsatz
von Recordset in einer Prozedur. Im Beispiel werden alle Datensätze der Tabelle Angestellte so modifiziert, dass der Lohn jedes Angestellten um 20% erhöht
wird.
Public Sub MehrLohnMitRecordset()
Dim rstAng As DAO.Recordset
Set rstAng = CurrentDb().OpenRecordset("Angestellte")
With rstAng
Do While rstAng.EOF = False
.Edit
!Lohn = !Lohn * 1.2
.Update
rstAng.MoveNext
Loop
End With
End Sub
Dieses Ziel könnte auch mit dem Einsatz von Execute und einem SQL-Ausdruck
wie im folgenden Beispiel erreicht werden.
Public Sub MehrLohnMitExecute()
CurrentDb().Execute "UPDATEAngestellte SET Angestellte.Lohn =" _
& "Angestellte.Lohn * 1.2;"
End Sub
38
KAPITEL 4. MS-ACCESS
Im allgemeinen ist eine Ausführung eines SQL-Ausdrucks schneller als die Datenmanipulation mit Hilfe von Recordset.
4.4
Sicherheit
Für die Sicherheit sind in Access verschiedene Mechanismen vorgesehen. Diese
Mechanismen sind wie folgt:
• Datensicherheit: Die Access Datenbank kann mit einem Passwort geschützt
werden. In diesem Fall wird jeder Benutzer beim Öffnen der Datenbank
aufgefordert, ein Passwort einzugeben. Diejenigen Benutzer, die das Passwort kennen, erhalten Zugriff auf die Datenbank und können (alle) Daten
in der Datenbank bearbeiten.
• Datensicherheit: In einer Access Datenbank existiert ein Mechanismus,
mit dessen Hilfe Benutzer und Gruppen definiert werden können. Den
Benutzern und Gruppen können so Zugriffsrechte exakt erteilt werden
und es wird definiert, wer welche Access-Komponente und darin enthaltene
Daten sehen, ändern oder löschen darf. Das ist die höchste Datensicherheit
in Access.
• Codesicherheit: Die Codes in einer Access Datenbank können mit einem
Passwort geschützt werden. Kennt ein Benutzer das Passwort, so darf er
Codes bearbeiten.
• Codesicherheit: Codes können auch gesichert werden, indem von der Datenbank eine MDE-Datei erstellt wird. In der MDE-Datei können keine
Codes bzw. keine Access-Komponenten mit Codes (Formulare, Berichte,
etc.) bearbeiten werden.
Jede Komponente in Access muss einen Namen haben. Die Komponenten, deren Name mit MSys oder USys anfangen sind als Systemkomponenten zu interpretieren. MSys steht für die Access-Systemkomponente und USys für die
Komponente, die der Benutzer als Systemkomponente bezeichnen möchte. Jede Access Komponente kann zusätzlich als ausgeblendet gekennzeichnet werden. Im Access-Hauptfenster (unter Extras → Optionen → Ansicht) kann eingestellt werden, ob die jeweilige Systemkomponente und/oder ausgeblendete
Komponente angezeigt werden dürfen. Dieser Mechanismus kann genutzt werden, um bestimmte Access-Komponente vor der direkten Sicht der Benutzer zu
verstecken. Trotzdem stellt dieser Vorgang keine dieser Komponenten richtig
sicher.
Kapitel 5
Ein Konzept für eine aktive
Erweiterung von Access
Access ist kein aktives Datenbankmanagementsystem und bietet demzufolge
Anwendern keine Möglichkeit an, um Trigger und Ereignismuster definieren zu
können. In diesem Kapitel wird untersucht, ob eine Trigger-Funktionalität in
Access realisiert werden kann. Im weiteren wird ein Konzept vorgestellt, wie
eine Erweiterung von Access um eine Regelsprache aussehen kann. Access kann
um eine Triggersprache erweitert werden, ohne dass ernsthafte Einschränkungen
zu erwarten sind. Da in Access und Jet Engine die Sourcecodes nicht veränderbar sind, lassen sich die notwendigen Anforderungen, die ein aktives Datenbankmanagementsystem erfüllen muss, nicht direkt im Access-Sourcecode programmieren. Diese Anforderungen betreffen vor allem Triggerverwaltung und
Ereigniserkennung. Damit Trigger und Ereignismuster definiert und Ereignisse
erkannt werden können, müssen diese Systeme in einem aktiven Datenbankmanagementsystem existieren.
5.1
Das Konzept eines Präprozessors
Eine Access-Anwendung ist eine Kombination von Access-Komponenten, deren
Zweck die Erledigung einer bestimmten Aufgabe ist. Die Trigger-Funktionalität
kann in Form einer Access-Anwendung unter Benutzung der Programmiersprache VBA programmiert werden. Diese Anwendung hilft zunächst dem Benutzer,
Trigger zu definieren. Weitere Aufgabe der Anwendung ist die Ereigniserkennung und die Bearbeitung der durch dieses Ereignis gefeuerten Trigger. Alle
Datenbankänderungen werden in Access mit Hilfe der Jet Database Engine
erledigt. Die Jet Engine ist eine Schnittstelle zwischen den Daten und der Benutzeroberfläche in Access. Die Oberflächen sind Access-Komponenten, durch
39
40
KAPITEL 5. KONZEPT
die Daten einer Access-Datenbank manipuliert werden können. Insbesondere wegen der Ereigniserkennung muss diese Anwendung zwischen Benutzerobeflächen
und der Jet Engine stehen. Bei diesem Konzept ist die Access-Anwendung eine
Schnittstelle zwischen Datenänderungsanforderungen und der Jet Engine (bzw.
den Daten). Die Anwendung funktioniert hier also wie ein Präprozessor zwischen Anwendern und dem Access(-Prozessor). Diesen Präprozessor nennen ich
ARTA. ARTA steht für ,,Active Real Time Access Database System”.
Das Bild 5.1 schildert die Beziehung zwischen ARTA und Access.
Benutuzer
ARTA
Jet DB Engine
Daten
Abbildung 5.1: ARTA in Access
Wie der Name ARTA sagt, wird mit diesem Präprozessor versucht, die
Aspekte ,,Aktivität” und ,,Zeitabhängigkeit” zu berücksichtigen. Durch ARTA
wird das Access-Datenbankmanagementsystem in ein aktives Access-Datenbankmanagementsystem überführt, in dem auch Zeitereignisse definiert und
wahrgenommen werden können. Dabei werden verschiedenen Typen von Ereignismustern definiert und die entsprechenden Ereignisse aufgefangen und bearbeitet. In ARTA existieren zwei Ereignistypen, Zeitereignisse und Änderungsereignisse. Änderungsereignisse treten bei Datensatzmanipulationen (an Access
Tabellen) auf, d.h. bei Löschen (DELETE), Hinzufügen (INSERT) oder bei
Änderung an Datensätzen (UPDATE). Zeitereignisse werden in zwei Untertypen aufgeteilt, absolute und periodische Zeitereignisse.
Die Kombination der Programmiersprache VBA mit dem Access-Datenbankmanagementsystem und der unter Access verwendeten SQL-Anfragesprache
ergibt ein potentes Werkzeug, mit dessen Hilfe man verschiedene Anwendungen
für Access programmieren kann. Dieses Werkzeug reicht für die Erweiterung
von Access um eine Triggersprache völlig aus. Das Access-Datenbankmanagementsystem bietet dem Programmierer seine Komponenten, z.B. Tabellen und
Formulare an, mit deren Hilfe die Trigger-Informationen verwaltet und gespei-
5.1. DAS KONZEPT EINES PRÄPROZESSORS
41
chert werden können. In VBA kann auf alle Access-Komponenten zugegriffen
werden und mit Hilfe von VBA-Methoden können Datenbankänderungen automatisch durchgeführt und beobachtet werden.
Die Anfragesprache SQL wird in Access in einem speziellen Dialekt unterstützt. Dieser Dialekt ist keine Einschränkung für die Formulierung der notwendigen SQL-Ausdrücke und erfüllt alle Anforderungen, die bei der Manipulation der Daten gestellt werden. Mit Access-SQL ist auch die Formulierung
von DDL1 -Befehlen z.B. ,,Create Table ...” möglich. SQL-Ausdrücke lassen sich
als Datenquelle für Formulare und Abfragen formulieren. Um die Einfachheit
von Access bezüglich der Datendefinition beizubehalten, werden als Eingabe in
ARTA nur die drei DML-Befehle DELETE, INSERT, UPDATE erlaubt sein.
In ARTA wird es z.B. nicht möglich sein, Tabellen zu definieren, oder Tabellendefinitionen (Evolution) zu ändern. Dazu stehen dem Benutzer alle Funktionalitäten von Access wie gewohnt zur Verfügung. SQL-Ausdrücke können auch in
einem VBA-Code ausgeführt werden (database.Execute(SQL)). Das ist besonders interessant, da auch die Folgeänderungen in Form eines SQL-Ausdrucks
eingegeben und im Code automatisch ausgeführt werden können. Diese Folgeänderungen sind insbesondere die Änderungen, die durch die Ausführung des
Aktionsteils eines gefeuerten Triggers zustande kommen können.
Die Benutzung von ARTA läuft unter einer Einschränkung. Diese Einschränkung hat ihre Ursache in der Ereigniserkennungsproblematik. In einer herkömmlichen Access-Datenbank werden Daten einer Tabelle wie folgt geändert:
• Die Änderung kann direkt an der Tabelle durchgeführt werden, nachdem
die Tabelle geöffnet wurde.
• Die Änderung kann indirekt durch ein Formular, das mit der Tabelle verknüpft ist, durchgeführt werden.
• Daten einer Tabelle können auch in einer Abfrage, deren Datenquelle diese
Tabelle ist, manipuliert werden.
Keine dieser Methoden eignet sich für die Erweiterung um eine Triggersprache, weil Datenänderungen bei diesen Methoden nicht als Ereignisse aufzufangen sind. Das wird noch problematischer, wenn andere Trigger durch den
Aktionsteil eines aktuell gefeuerten Triggers gefeuert werden sollen. Diese sogenannten Folgeänderungen müssen automatisch durchgeführt werden. Die in Access üblichen Datenbankänderungesarten sollten durch ARTA übergangen werden, d.h. alle Datenbankänderungsbefehle sollten in ARTA eingegeben werden.
1
Data Definition Language
42
KAPITEL 5. KONZEPT
Die Ausführung dieser Befehle wird dann von ARTA kontrolliert durchgeführt.
Dafür wird in ARTA eine Oberfläche vorgesehen, in der alle Änderungsbefehle
der Form ,,DELETE, INSERT, UPDATE” eingegeben werden sollen.
Ein Mechanismus in Access sorgt hier für Missverständnisse. Die Frage stellt
sich, warum die Formular-Ereignisse nicht benutzt werden können, um Ereignisse aufzufangen. Ereignisse könnten doch ,,innerhalb” eines Formulars automatisch erkannt werden. Trigger könnten so in dem Formular-Klassenmodul
mit Hilfe von Funktionen und Subs formuliert werden. Ein Formular muss mit
einer bestimmten Tabelle verknüpft sein, damit der Benutzer Datenänderungen
an der Tabelle über dieses Formular vornehmen kann. Daten der jeweiligen Tabelle müssen deshalb nur über dieses Formular modifiziert werden, um sie als
Ereignisse wahrgenommen zu werden. Trigger müssen deswegen einzeln zu jeder
Tabelle in einem separaten Formular mit Hilfe der Programmiersprache VBA
,,programmiert” werden. Hier fehlt jedoch ein Zentralsystem für die Triggerbearbeitung.
Im übrigen können die vom Aktionsteil eines Triggers angeforderten Datenänderungen an einer anderen Tabelle nicht durchgeführt werden, es sei denn
aus einem Formular werden andere Formulare geöffnet und die Folge-Änderungen werden in neu geöffneten Formularen durchgeführt. Dabei ist zu beachten,
dass alle beteiligten Formulare mit geeigneten Tabellen verknüpft sein müssen.
Diese Art von Triggerdefinition und Triggerbearbeitung ist nicht realistisch. Zusammengefasst sind die Formular-Ereignisse nicht geeignet, um ein automatisches Triggerbearbeitungssystem zu realisieren. Formular-Ereignisse eignen sich,
die Definition und Änderung von Triggern zu überwachen. Dafür wird einzig die
Syntaxprüfung durch die Formular-Ereignisse mit Hilfe von VBA programmiert.
Ein Trigger in ARTA besteht aus allgemeinen Informationen über den Trigger und aus drei weiteren Grundteilen: Ereignismusterteil (Event), Bedingungsteil (Condition) und Aktionsteil(Action). Die allgemeinen Informationen eines
Triggers sind vor allem der Name und die Priorität des Triggers. Im Falle eines Änderungsereignisses können auch Parameter vordefiniert werden, die Informationen über die betroffenen Datensätze (Zeilen) der Tabelle enthalten.
Die betroffenen Zeilen sind die Datensätze, die durch die Ausführung eines
SQL-Datenbankänderungsbefehls geändert werden. Die Anzahl der betroffenen
Zeilen können auch Null sein, d.h. trotz der SQL-Ausführung werden keine Datensätze eingefügt, gelöscht oder geändert. Der Ereignismusterteil eines Triggers
hat einen eindeutigen Namen. Mit diesem Namen sind die weiteren Informationen des Ereignismusters verknüpft. Die weiteren Informationen sind vor allem
das Erzeugungsdatum, das Datum der letzten Änderung des Ereignismusters
5.1. DAS KONZEPT EINES PRÄPROZESSORS
43
und der Ereignismustertyp. Je nach Ereignismustertyp gehören dem Ereignismuster spezifische Eigenschaften an.
Zum Ereignismuster vom Typ ,,Änderungsereignis” gehören der Tabellenname und der DML2 -Befehl. Einem Ereignismuster vom Typ ,,Zeit-EreignisatOnce” gehören date, time und deadLine an. Begin-date, Begin-time, deadLine und die Periode gehören zu einem Ereignismuster vom Typ ,,Zeit-Ereignisperiodic”. Zeitereignisse werden in einem gesonderten Abschnitt beschrieben.
Änderungsereignismuster in ARTA sind dem SQL3-Standard3 sehr ähnlich, da
ARTA auf dem SQL3 basiert. Im Unterschied zum SQL3-Standard werden in
ARTA Änderungsereignisse nur auf der Ebene von Tabellen definiert. Eine Datenänderung auf einem bestimmten Feld einer Tabelle kann ja als eine Datenänderung auf der Tabelle interpretiert werden.
In SQL existiert keine ja/nein Abfrage, mit SELECT formulierte Abfragen
geben eventuell ausgewählte Datensätze zurück. Für den Bedingungsteil eines
Triggers in ARTA können ja/nein Abfragen durch die Definition bestimmter
Funktionen realisiert werden. Eingabeparameter einer solchen Funktion könnte z.B. ein SQL-Ausdruck sein und die Funktion gibt zurück, ob durch diesen
SQL-Ausdruck Datensätze ausgewählt werden (z.B. ExistElement(SQL)). Eine mögliche Triggerbedingung ist auch ein Vergleich vordefinierter Parameter,
Konstanten oder der aktuellen Zeit miteinander, z.B.
NewRowPar.Verlaengerung um > 42. Standardmäßig wird eine leere Triggerbedingung als ,,ja(True)” interpretiert. Der Aktionsteil eines Trigger ist ein
ausführbarer Ausdruck. Als Triggeraktion ist in ARTA im Unterschied zu SQL3
ein einziger zusammengehörender Ausdruck erlaubt. Dieser Ausdruck kann eine
in VBA vorhandene oder vom Benutzer neu eingebaute Funktion sein. In einer
vom Benutzer eingebauten Funktion kann programmiert werden, dass mehr als
ein Befehl ausgeführt wird.
Durch diese Methode kann der Aktionsteil eines Triggers eine Funktionalität aufweisen, die auch in SQL3 vorgesehen ist. Diese Funktionen sollten als
globale Funktionen und in Modulen (nicht in Klassenmodulen) definiert sein,
da die in einem Klassenmodul definierten Funktionen nur durch initiierte Objekte aufrufbar sind. Aber die in einem Modul als global definierte Funktion
ist überall in VBA und sogar in Access-Komponenten ausführbar. Dabei ist
hinzuzufügen, dass diese Methode nicht für jeden Benutzer geeignet ist. Diese
Methode ist eher für die Benutzer geeignet, die die Programmiersprache VBA
2
3
Data Manipulation Language
Vgl. 2.2
44
KAPITEL 5. KONZEPT
beherrschen. In der Implementierung von ARTA werden Funktionen vorgestellt,
die auch nicht VBA-Programmierer anwenden können.
Unterschiede zwischen den Triggersprachen in ARTA und SQL3:
Eine Zusammenfassung der Unterschiede zwischen der SQL3- und ARTATriggerfunktionalität wurde in der Tabelle 5.1 gegeben. Im Vergleich zu SQL3
ist die Behandlung von Zeitereignissen in ARTA als eine Erweiterung zu betrachten. In SQL3 werden nur Änderungsereignisse spezifiziert, die im Ereignisteil von Triggern beschrieben werden. Zusätzlich dazu werden in ARTA auch
Zeitereignisse behandelt, die im Ereignisteil von ARTA-Triggern beschrieben
werden.
Zeitereignisse
Für die Realisierung von Zeitereignissen bzw. Timern existieren folgende
Möglichkeiten in Access und VBA:
• Formularereignis: (Bei Zeitgeber)
Über das Formularereignis ,,Bei Zeitgeber” kann in einem Formular eingestellt werden, dass eine Prozedur in seinem Klassenmodul periodisch in
gleichen Zeitabständen (in Millisekunden) ausgeführt wird.
• Durch Benutzung des Befehls ,,DoEvents” in einer Prozedur kann eine
bestimmte Funktion in gleichen Zeitabständen aufgerufen werden. In der
folgenden Prozedur wird alle 4 Sekunden die aktuelle Zeit ausgegeben:
Public Sub Timer()
Dim dte As Date
Do While True
Debug.Print Now()
dte = Now()
Do While (4 > DateDiff("s", dte, Now()))
DoEvents
Loop
Loop
End Sub
• Mit Hilfe von API-Schnittstelle.
Für die Realisierung von Timern in ARTA wurde die Methode von APISchnittstelle ausgewählt. Die Methoden und die Benutzung von API-Funktionen
wurden im Kapitel 6 ausführlich beschrieben. Die API-Schnittstelle wurde aus
5.1. DAS KONZEPT EINES PRÄPROZESSORS
Art der
Ereignisse
Definition
von Triggern
und Ereignismustern:
Triggerbearbeitung
45
SQL3
ARTA
In SQL3 werden Zeitereignisse überhaupt nicht unterstützt.
Ereignismuster haben keine Namen (Bezeichnungen),
so muss für jeden Trigger
ein Ereignismuster angegeben werden.
In ARTA besteht die
Möglichkeit, Zeitereignisnuster zu definieren.
Jedes Ereignismuster hat
einen Namen (Bezeichnung),
so kann ein schon definiertes Ereignismuster bei mehreren Triggern benutzt werden.
Ereignismuster können nur
bis zu der Tabellenebene
spezifiziert werden
Im Aktionsteil eines Triggers
kann nur ein einziger Befehl
stehen. Dieser Befehl kann
ein Funktionsaufruf oder ein
SQL-Ausdruck sein.
Ereignismuster können bis
zu der Felderebene spezifiziert werden
Im Aktionsteil eines Triggers, zwischen ,,BEGIN
ATOMIC” und ,,END”
können
mehrere
SQLAusdrücke eingesetzt werden. Das funktioniert wie
eine Prozedur, in der auch
z.B. Schleifen vorkommen
dürfen.
Integritätanforderungen
werden bei der Triggerbearbeitung berücksichtigt
Zeitereignisse werden nicht
abgefangen.
Integritätanforderungen
werden bei der Triggerbearbeitung nicht berücksichtigt.
Zeitereignisse, die durch geeignete Ereignismuster spezifiziert sind, werden abgefangen und deren Trigger
werden bearbeitet.
Tabelle 5.1: Unterschiede zwischen der SQL3- und ARTA-Triggersprache
46
KAPITEL 5. KONZEPT
folgenden Gründen ausgewählt. Jeder API-Timer läuft in einem eigenen Prozess im Betriebsystem parallel zu Access. Deswegen braucht ein API-Timer im
Vergleich zur Methode ,,Formularereignis” kein Access-Objekt. Ein API-Timer
wird direkt vom Betriebsystem verwaltet. So braucht er keine großen Resourcen, dagegen beschäftigt die Methode mit dem Befehl ,,DoEvents” ständig den
Rechnerprozessor.
Ein Nachteil - oder besser formuliert: eine Eigenschaft - von API ist die hohe Sensibilität, die im Abschnitt 3.3 genauer beschrieben wurde. Das ist besonders bei API-Timern problematisch, weil diese Funktionen eine Rückruffunktion
benötigen. Die Rückruffunktionen dürfen nicht lange warten müssen und sollten schnell bearbeitet werden. Es gibt Konfliktzustände, bei denen Access ohne
Vorwarnung abstürzt: z.B. beim mehrmaligen Aufruf derselben Rückruffunktion
durch mehrere Timer. Um dieses Problem zu lösen wird vereinbart, dass gleichzeitig nur ein einziger Timer eingesetzt werden darf. Konflikte kommen nach
dieser Methode überhaupt nicht zustande, weil eine Ausführung der Rückruffunktion zu Ende gehen soll, bevor die Rückruffunktion erneut aufgerufen wird.
Die sichere Ausführung eines (SQL-)Befehls
Was passiert mit der Bearbeitung eines SQL-Befehls bzw. von Triggern (die
durch ein Ereignis gefeuert wurden) wenn Access vorher geschlossen wird? Es
kann möglicherweise vorkommen, dass ein Benutzer versucht Access zu schließen, obwohl die Datenbankänderungen nicht vollständig abgeschlossen sind.
solche Datenbankänderungen werden erst dann einen Sinn machen, wenn alle zusammengehörenden Trigger vollständig bearbeitet werden. Bei folgendem
Beispiel darf Access erst nach dem Schritt ,,n)” geschlossen werden.
0)Anfang der Bearbeitung von SQL S
1)S erzeugt das Ereignis E und E feuert {T1 ,T2 ,T3 },
2)T1 .Aktion erzeugt das Ereignis E1 und E1 feuert {T11 ,T12 ,. . . },
3)T2 .Aktion erzeugt das Ereignis E2 und E2 feuert {T21 ,T22 ,. . . },
...
n)Ende der Bearbeitung von SQL S.
Zur Lösung dieses Problems wird wieder ein Formularereignis benutzt. Die
Prozedur ,,Private Sub Form Unload(Cancel As Integer)” wird beim Schließen
des Formulars (Formular-Ereignis: ,,Bei Entladen”) aufgerufen. Wenn die Variable ,,Cancel=True” ist, darf (kann) das Formular nicht geschlossen werden,
und demzufolge kann Access auch nicht geschlossen werden. Bei Beginn einer
Triggerbearbeitung wird in einem (unsichtbar) geöffneten Formular die Variable ,,Cancel” auf ,,True” gesetzt. Nach der Beendigung der Triggerbearbeitung
5.2. SYNTAX VON ARTA-TRIGGERSPRACHE
47
wird wieder die Variable ,,Cancel” auf ,,False” zurückgesetzt.
Private Sub Form_Unload(Cancel As Integer)
If Not Me.chk_EnableClose Then
Cancel = True
End If
End Sub
,,chk EnableClos” ist ein Kontrollkästchen, das im Formular eingebaut wurde.
Mit der Inhaltsänderung dieses Kontrollkästchens wird indirekt der Variableninhalt ,,Cancel” wie folgt kontrolliert:
Forms("USys_frm_ControlSystemClose")!chk_EnableClose = False/True
Damit wird gewährleistet, dass die Bearbeitung vollständig durchgeführt werden
kann.
5.2
Syntax von ARTA-Triggersprache
Die Syntax eines triggers in ARTA-Triggersprache sieht bis auf ein paar Einschränkungen fast genauso aus wie die Syntax eins Triggers bei SQL3. Ein
Trigger wird unter ARTA nicht in Form eines Textes definiert. Er wird in einem Formular definiert, in dem bestimmte Felder für Einträge vorgesehen sind.
Bei der Syntax-Beschreibung von ARTA in BNF4 -Form existieren deswegen
Ausdrücke, die bei einer Triggerdefinition nicht eingegeben werden. Diese Ausdrücke werden zum besseren Verständnis der Grammatik benutzt. Die Syntax
eines Triggers in BNF-Form sieht wie folgt aus:
<trigger definition> ::=
CREATE TRIGGER
<trigger name> <trigger priority> <trigger activity>
<trigger event>
<trigger condition>
<trigger action>
<trigger condition> ::=
WHEN {<left paren> <search condition> <right paren>
|<function>}
<trigger action> ::= <SQL Statement> | <VBA function>
4
Backus-Naur-Form: Vgl. [AutoHoUl]
48
KAPITEL 5. KONZEPT
<trigger event> ::=
<modify>
| <atOnce>
| <periodic>
<modify>::=
<event name> <trigger action time> <trigger DML>
ON <table name> [ REFERENCING <old new values alias list>]
FOR EACH {ROW | STATEMENT}
<trigger action time> ::=
BEFORE
| AFTER
<trigger DML> ::=
INSERT
| DELETE
| UPDATE
<old or new values alias list> ::=
<old or new values alias>...
<old new values alias> ::=
OLD ROW AS <old values correlation name>
| NEW ROW AS <new values correlation name>
| OLD TABLE AS <old values table alias>
| NEW TABLE AS <new values table alias>
<old values table alias> ::=<identifier>
<new values table alias> ::=<identifier>
<old values correlation name> ::= <correlation name>
<new values correlation name> ::= <correlation name>
<atOnce> ::=
<date> <time>
<deadLine>
5.2. SYNTAX VON ARTA-TRIGGERSPRACHE
49
<periodic> ::=
BEGIN
<date> <time> <deadLine>
EVERY
{<number> <period>
|<number> <period> + <number> <period>}
<number> ::= 1,2,3,...
<period> ::=
minutes
| hours
| days
| weeks
| months
| years
Dabei bedeuten die Parameter wie folgt:
<trigger name>: Eindeutiger Name für den Trigger.
<trigger priority>: Eine eindeutige natürliche Zahl
<trigger activity>: ja/nein-Eintrag.
<left paren><search condition> <right paren>: An dieser Stelle können ja/neinAbfragen an die Datenbank formuliert werden.
<function>: Globale Funktionen, die entweder in VBA oder von Benutzern definiert wurden.
<SQL Statement>: Ein SQL-Ausdruck.
<event name>: Ein eindeutiger Name für das Ereignismuster.
<identifier>: Eindeutige Namen für die Parameter.
<correlation name>: Eindeutige Namen für die Parameter.
<date>: Das Datum des Tages, an dem ein Ereignis auftritt.
<time>: Die Tageszeit.
<deadLine>: Eine natürliche Zahl ≥ 5 Minuten.
Wie schon erwähnt, werden die Trigger in ARTA formularbasiert verwaltet. Die Syntax von ARTA-Regeln muss in zwei voneinander abhängigen Teilen
beschreiben werden.
5.2.1
Syntax eines Triggers
Trigger werden in einem Formular definiert, in dem folgende Felder vorgesehen
sind:
50
KAPITEL 5. KONZEPT
• Ein eindeutiger Triggername:
Ein Trigger wird in einer ARTA-Datenbank eindeutig bestimmt und definiert. Der Name darf 1 bis 64 Zeichen aus der Menge der ,,legalen Zeichen”
,,{a,b,. . . ,z,A,B,. . . ,Z,0,1,. . . ,9, }” enthalten. Triggernamen sollten aussagefähig ausgewählt werden, damit die Unterschiede zwischen Triggern aus
ihren Name ersichtlich werden.
• Eine eindeutige Trigger-Priority:
Trigger-Priority ist eine Zahl aus der Menge der natürlichen Zahlen
{1,2,3,4. . . }. Durch Trigger-Priority wird die eindeutige Reihenfolge der
Bearbeitung der betroffenen Trigger an den Konfliktstellen bestimmt.
• Ist aktiv:
Die Aktivität eines Triggers gibt an, ob dieser Trigger beim Auftreten
eines Ereignisses berücksichtigt werden darf.
• Created und Modified Dates:
Das Datum des Erzeugens und das Datum der letzten Änderung eines
Triggers werden automatisch hier eingesetzt.
• Event: Das Ereignismuster beschreibt das Ereignis, dessen Eintritt dieser Trigger feuert. Die Syntax von Ereignismusterdefinitionen wird weiter
unten in 5.2.2 beschrieben.
• REFERENCING: An dieser Stelle ist die Definition von bis zu vier Parametern möglich. Je nach Art des Ereignismusters können Parameter für
NEW TABLE, OLD TABLE, NEW ROW, OLD ROW eingegeben werden. Bei den Zeitereignissen werden keine Parameter definiert.
Bei einem Änderungsereignis dürfen je nach DML-Befehl folgende Parameter definiert werden:
– Bei dem Befehl DELETE dürfen OLD TABLE und OLD ROW definiert werden.
– Bei dem Befehl INSERT dürfen NEW TABLE und NEW ROW definiert werden.
– Bei dem Befehl UPDATE dürfen OLD TABLE, OLD ROW,
NEW TABLE und NEW ROW definiert werden.
• Action-Time:
Ob der Trigger vor oder nach der SQL-Ausführung bearbeitet werden soll,
5.2. SYNTAX VON ARTA-TRIGGERSPRACHE
51
wird durch diesen Eintrag bestimmt. Action-Time ist bei einem Änderungsereignismuster entweder BEFORE oder AFTER. Standardeintrag
ist ,,BEFORE”.
• FOR EACH ist bei einem Änderungsereignismuster entweder ROW oder
STATEMENT, wobei der Standardeintrag ,,STATEMENT” ist.
• Condition:
Unter diesem Eintrag wird eine ja/nein Anfrage formuliert. Diese Anfrage
kann aus einem Funktionsaufruf oder einem logischen Vergleichsausdruck
bestehen. Konstanten und Parameter, die mit dem Trigger definiert wurden, können in Funktionen als Eingabeparameter und in logischen Ausdrücken als Variablen benutzt werden. In logischen Ausdrücken sind die
Vergleichsoperatoren {<, <=, >, >=, =, <>} erlaubt.
• Action:
Unter diesem Eintrag wird ein Befehl formuliert, der nach dem Feuern des
Triggers ausgeführt wird, wenn die Triggerbedingung (Condition) erfüllt
ist. Die vom Benutzer eingebauten globalen Funktionen, die Access Funktionen und SQL-Ausdrücke können hier eingegeben werden. Auch im Triggeraktionsteil können Triggerparameter vorkommen.
5.2.2
Syntax eines Eventmusters
Ereignismuster müssen gesondert (aber gleichzeitig mit Triggern) definiert
werden. Ein vorher gleichzeitig mit einem Trigger definiertes Ereignismuster kann als Ereignisteil eines anderen Triggers benutzt werden. Ein Ereignismuster darf nur dann geändert werden, wenn das Ereignismuster entweder als Eventteil eines einzigen Triggers benutzt worden ist, oder wenn
das Ereignismuster falsch eingegeben wurde. Ein Ereignismuster wird in
einem Formular mit den folgenden Textfeldern definiert.
• Name ist eine eindeutige Bezeichnung des Ereignismusters.
• Created und Modified Date sind die Erzeugungs- bzw. Änderungsdaten, die automatisch eingesetzt werden.
• Je dem Event-Typ müssen gezwungener Massen andere Eigenschaften
für das Ereignismuster definiert werden:
– Bei modify event müssen der Datenbankmanipulationstyp, DMLTyp und der Tabellenname eingegeben werden.
52
KAPITEL 5. KONZEPT
Ein DML-Befehl kann vom Typ DELETE, INSERT oder UPDATE
sein. Bei dem Feld, in das auf diesem Formular dieser DML-Befehl
eingegeben wird, ist nur einer der o.g. Befehle als Eingabe möglich.
Der Tabellenname darf nur von der Liste der vorhandenen Tabellen
in der Datenbank gewählt werden.
– Bei time event atOnce sind folgende Informationen relevant:
date: der Tag, an dem das Zeitereignis erwartet wird.
time: die Uhrzeit im unter date eingegebenen Tag.
deadLine: Beim Eintreffen des Zeitereignisses darf der Trigger nur vor
dem Ablauf dieser Deadline gefeuert werden. Wenn ein Zeitereignis
nach dem Ablauf der Deadline eintritt, werden seine Trigger ignoriert.
Die Deadline wird in Minuten eingegeben und darf nicht kleiner als
5 Minute sein. Wenn keine Zahl eingegeben wird, wird die Deadline
als unendlich(∞) angenommen.
– Bei time event periodic muss eingegeben werden, ab wann und in
welchen Zeitabständen solche Zeitereignisse bemerkt werden. Nach
einer erfolgreichen Eingabe solcher Ereignismuster wird der nächste
Termin automatisch berechnet und als informativer Eintrag angezeigt. Die periodischen Zeitereignisse dürfen nicht mehr geändert
werden, sobald sie richtig eingegeben und die nächsten Termine berechnet wurden. Die Einträge sind Begin-date, Begin-time, deadLine
und Periode. Die Periode ist die Summe von zwei Teilperioden. Die
Deadline hat hier genau die gleiche Funktionalität wie bei dem oben
genannten time event atOnce Ereignismuster.
Ein Ereignismustertyp hat direkten Einfluss auf folgende Parameter von
Triggern.
• Die Auswahl eines Ereignismusters vom Typ modify event veranlasst,
dass die folgende Felder sichtbar werden: Action-Time und FOR EACH,
die oben bereits beschrieben wurden. Wenn der Ereignismustertyp ,,modify event” gewählt wird, so müssen der DML-Befehl und der TabellenName eingegeben werden. Nach der Eingabe des DML-Befehls werden
Felder für folgende Triggerparameter sichtbar.
– Ist der DML-Befehl DELETE, dann sind OLD TABLE und
OLD ROW sichtbar.
– Ist der DML-Befehl INSERT, dann sind NEW TABLE und
NEW ROW sichtbar.
5.3. SEMANTIK DER ARTA-TRIGGERBEARBEITUNG
53
– Ist der DML-Befehl UPDATE, dann sind alle Parameter
NEW TABLE , NEW ROW , OLD TABLE und OLD ROW sichtbar.
In sichtbare Felder können Einträge eingegeben werden. Diese Felder müssen aber nicht ausgefüllt werden, es sei denn der Benutzer hat vor, diese in
anderen Triggerteilen (Triggercondition oder Triggeraction) zu benutzen.
• Bei Ereignismustern vom Typ atOnce oder periodic sind keine der o.g.
Triggerparameter erlaubt und deswegen bleiben die entsprechenden Felder
unsichtbar.
5.3
Semantik der ARTA-Triggerbearbeitung
11 12 1
2
10
9
3
8
4
7 6 5
Benutzeroberfläche
Verwaltung von
Zeitereignissen
S
VvZE
Bearbeitung von
Aftertriggern
S
Feuert
S
Trigger?
Nein
S
Ausführen
BvA
Nein
Ja
Feuert
S Aftertrigger?
Bearbeitung von
Beforetriggern
BvB
Nein
Ende der Bearbeitung
Befehlsausführungssystem
BAS
Abbildung 5.2: Triggerbearbeitung in ARTA
Im Bild 5.2 wurde der Flussdiagramm der Triggerbearbeitung in ARTA geschildert. S ist ein (SQL-)Befehl, der entweder von einem Benutzer aus dem
ARTA-Hauptfenster (Benutzeroberfläche) eingegeben wird oder die Ausgabe
von VvZE5 ist. Tritt ein Änderungsereingis wegen Ausführung des Befehls S
5
Verwaltung von Zeitereignissen wird in 5.4 beschrieben.
54
KAPITEL 5. KONZEPT
ein, wird die Menge von gefeuerten Beforetriggern berechnet, in der diese Beforetrigger nach ihren Prioritäten sortiert werden. Nach dem Sortieren werden die
Beforetrigger in einer Schleife bearbeitet. Nach der Bearbeitung von Beforetrigger soll der Befehl S ausgeführt werden. Als nächstes wird die Mange von Aftertriggern bestimmt, die an dieser Stelle nach ihren Prioritäten sortiert werden. In
einer Schleife werden Aftertrigger bearbeitet, indem Aktionsteile von Aftertriggern als neuer S-Befehl in BAS eingegeben werden und BAS(Aftertrigger.action)
ausgeführt wird.
Für die Bearbeitung von Before- und Aftertriggern sollen zuerst die vordefinierten Parameterinhalte berechnet werden, weil vor Bedingungsuswertung
sowie vor der Ausführung von BAS(Aftertrigger.action) diese Parameter in Triggerbedingungsteil und Triggeraktionsteil durch ihre Inhalte ersetzt werden sollen. Die Parameter werden zu jedem Befehl berechnet und für die Bearbeitung
von Before- und Aftertriggern eingesetzt. Die Bearbeitung von einem Befehl
wird vollständig in BAS durchgeführt, indem auch die internen Variablen beschrieben werden.
Eintritt von Änderungsereignissen
Der SQL-Ausdruck ,,S” wird als Eingabe ins Befehlsausführungssystem (BAS)
hinzugefügt. In BAS wird zuerst getestet, ob durch Ausführung von S ein definiertes Ereignis eintritt und dieses Ereignis Trigger feuert. Ist das nicht der Fall,
so wird S ausgeführt, ohne ein Triggerbearbeitung durchzuführen. Feuert die
Ausführung von S Trigger (Tritt ein Änderungsereignis ein), werden die gefeuerten Trigger bearbeitet. Die Semantik der Triggerbearbeitung im ARTA ist bis
auf einige Unterschiede auf die im SQL3 vorgestellte Semantik aufgebaut. Im
folgenden wird die Prozedur ,,Befehlsausführungssystem (BAS)” beschrieben,
die Ausführung eines SQL-Befehls beobachtet und gefeuerte Trigger bearbeitet:
Anfang von BAS(S)
Nach der Eingabe des SQL-Befehls wird ein so genannter Trigger Execution
Context (TEC) erzeugt, der besteht aus
• einer Menge von Transitionen TRN,
• dem Namen der betroffenen Tabelle,
• dem Typ des Ereignisses (DELETE | INSERT | UPDATE).
Die Menge der Transitionen besteht aus zwei Transitionstabellen. Die Transitionstabellen beinhalten Datensätze, die durch Korrelationen zwischen zwei
5.3. SEMANTIK DER ARTA-TRIGGERBEARBEITUNG
55
Zuständen der Originaltabelle vor der SQL-Ausführung und nach der SQLAusführung enstehen können. Die betroffenen Datensätze werden in zwei temporären Tabellen gespeichert. Die Ausführung eines SQL-Ausdrucks und die Bearbeitung der von ihm betroffenen Trigger werden in einer Transaktion durchgeführt. Die temporären Tabellen sollen bis Ende der aktuellen Transaktion
existieren. Weil die temporären Tabellen nur während der aktuellen Transition
benötigt werden, sollen sie dann nach der Beendigung der Transaktion gelöscht
werden.
Die alten Datensätze werden in der ,,OLD Transitionstabelle” und die neuen
Datensätze in der ,,NEW Transitionstabelle” zwischengespeichert. Die Transitionstabellen können Daten enthalten, wenn überhaupt Datensätze von der
Originaltabelle betroffen sind. Dabei ist nicht unwahrscheinlich, dass Anwendung eines SQL-Befehls Datenbank nicht ändert. Das WHERE-Teil eines SQLAusdrucks kann so formuliert werden, dass durch den SQL-Ausdruck keine Datensätze ausgewählt werden. Auch der Zustand von Tabellen spielt eine große
Rolle, ob Datensätze betroffen werden, wie z.B. aus einer leeren Tabelle können
keine Datensätze ausgewählt werden. Je nach DML-Befehl können beide oder
nur eine der Transitionstabellen Daten beinhalten:
• Bei DELETE kann nur die OLD Transitionstabelle Daten enthalten.
• Bei INSERT kann nur die NEW Transitionstabelle Daten enthalten.
• Bei UPDATE können beide OLD Transitionstabelle und
NEW Transitionstabelle Daten enthalten.
Nachdem TEC berechnet und bereitgestellt wurde, soll die Menge BTrs
bestimmt werden. BTrs besteht aus Beforetriggern, die durch das Ereignis
(Ausführung von S) gefeuert werden. Falls die Menge der Transitionen leer ist,
werden alle ROW-Level-Beforetrigger aus der Menge BTrs entfernt, weil ROWLevel-Trigger nur für jede betroffene Zeile gefeuert werden dürfen. Betrifft der
SQL-Ausdruck keine Zeile der Tabelle, so wird kein ROW-Level-Trigger bearbeitet.
An dieser Stelle werden die Beforetrigger nach ihren Erzeugungsdatum sortiert. Alle (bzw. übrige) Beforetrigger werden in einer Schleife abgearbeitet.
Dabei werden die Statement-Level-Trigger nur einmal und ROW-Level-Trigger
für jede betroffene Zeile einmal wie folgt bearbeitet. Für jeden Trigger T in
BTrs:
• T ist ein STATEMENT-Level Trigger:
56
KAPITEL 5. KONZEPT
1. Die Inhalte von Triggerparametern sollen aus den Transitionstabellen
berechnet werden.
2. Nach dem Ersetzen die Parameter durch deren Inhalte in den Triggerbedingungs- bzw. in den Triggeraktionsteil von T, wird die Bedingungsauswertung durchgeführt.
3. Ist das Ergebnis der Bedingungsauswertung = True, dann wird Triggeraktion ausgeführt, ohne weitere Trigger zu feuern.
• T ist ein ROW-Level Trigger:
Hier soll für jede betroffene Zeile:
1. Die Parameterinhalte werden aus den Transitionen berechnet.
2. Die Parameter werden durch ihre Inhalte in Bedingungsteil und Aktionsteil von T ersetzt und die Bedingungsauswertung wird durchgeführt.
3. Gibt Bedingungsauswertung ,,True” zurück, wird Triggeraktion ausgeführt (wieder ohne Trigger zu feuern).
Alle Beforetrigger wurden bis hierhin abgearbeitet. An dieser Stelle wird der
SQL-Ausdruck S ausgeführt. Nach der S-Ausführung wird die Menge ATrs bestimmt, die aus Aftertriggern besteht, die das Ereignis ,,S-Ausführung” feuert.
Ist TRN (die Menge der Transitionen) leer, werden alle ROW-Level-Trigger
aus der Menge ATrs entfernt. Für jeden Trigger T in ATrs gilt:
• T ist ein STATEMENT-Level Trigger:
1. Die Parameterinhalte sollen aus der Transitionstabellen berechnet
werden.
2. Nach dem Ersetzen die Parameter durch ihre Inhalte in Condition und Actionateil von T, wird die Bedingungsauswertung durchgeführt.
3. Ist das Ergebnis der Bedingungsauswertung = True, soll Triggeraktion als eine neue Eingabe S in das Befehlsausführungssystem eingegeben werden und BAS(S:=Triggeraction) ausgeführt werden
(Rekursion).
• T ist ein ROW-Level Trigger:
Für jede betroffene Zeile:
1. Die Parameterinhalte werden aus den Transitionen berechnet.
5.3. SEMANTIK DER ARTA-TRIGGERBEARBEITUNG
57
2. Die Parameter werden durch ihre Inhalte in Bedingungsteil und Aktionsteil von T ersetzt und die Bedingungsauswertung wird durchgeführt.
3. Gibt Bedingungsauswertung ,,True” zurück, soll Triggeraktion als
eine neue Eingabe S in das Befehlsausführungssystem eingegeben
werden, d.h. BAS(S:=Triggeraction) (Rekursion.
Wie es aus der Semantikbeschreibung ersichtlich ist, wird die Bearbeitung von
Triggern durch Einsatz der Rekursion erledigt. Durch den rekursiven Aufruf der
Prozedur werden voneinander unabhängigen Instanzen von dieser Prozedur erzeugt. Jeder Prozeduraufruf deklariert seine eigenen Variablen (vor allem TEC)
und läuft erst dann zu Ende, nachdem alle durch sie aufgerufene Instanzen zu
Ende durchgeführt sind.
Bearbeitung von
Beforetriggern
SQL-Ausführung
Ereignis
Bearbeitung von
Aftertriggern
E
E1
E 11
E2
E 12
...
En
E 1m
...
...
E i1
...
E i2
...
E ij
Abbildung 5.3: Instanzorientierte Triggerbearbeitungssemantik
Instanzorientierte Regelbearbeitung
Durch Rekursion wird die Triggerbearbeitungssemantik in ARTA instanzorientiert. Mit der instanzorienterten Semantik wird die Triggerbearbeitung in
58
KAPITEL 5. KONZEPT
Tiefe durchgeführt, durch die die Bearbeitung von Triggern insoweit in die Tiefe
weitergeleitet wird, bis keine Aftertrigger mehr gefeuert werden. Danach wird
die Bearbeitung in einer Stufe höher weiter durchgeführt. Im Bild 5.3 wurde die
Instanzorientierung der Triggerbearbeitung von ARTA geschildert.
5.4
Verwaltung von Zeitereignissen
Zeitereignisse sind in ARTA in zwei Untertypen aufgeteilt: absolute und periodische Zeitereignisse. Absolute Zeitereignisse treten nur einmal an einem bestimmten Zeitpunkt auf. Periodische Zeitereignisse treten wiederholt in gleichen
Zeitabständen auf. Ein periodisches Zeitereignismuster wird nach jedem Eintreten seines Zeitereignisses modifiziert, indem für das Zeitereignismuster ein neuer Termin berechnet wird. Dieser neue Termin wird zum ersten Mal nach der
erfolgreichen Ereignismusterdefinition berechnet. Der neue Termin, d.h. wann
das periodische Zeitereignis nochmal eintritt, ergibt sich sich aus der Addition des Anfangstermins bzw. des aktuellen Termins mit der Periode. Wie schon
in diesem Kapitel erwähnt wurde, wird in ARTA immer nur maximal ein Timer gesetzt. Im Bild 5.4 wird die Arbeitsweise der Zeitereignisbearbeitung und
System anschalten
(Datenbank öffnen)
Inerres Zeitereignis
Wurde ein Zeit-Ereignis ( ZE ) in
der Vergangenheit geschehen
und darf noch Trigger
feuern(deadLine)?
Ist ein Ereignis in weniger
als einer Woche zum
Nein
Zeitpunkt t
zu erwarten?
schicken.
Nein
Timer setzen für
einen Tag
Ja / t
Ja / ZE
ZE an Zeitereignisbearbeitungssytem
11 12 1
2
10
9
3
8
4
7 6 5
ZE
11 12 1
2
10
9
3
8
4
7 6 5
Timer setzen zum
t
Warten bis alle durch
ZE gefeuerten
Trigger bis zum Ende abgearbeitet sind.
Abbildung 5.4: Flußdiagram zu der Zeitereignisbearbeitung
Timerverwaltung geschildert. Immer beim Einschalten des System sowie nach
einer durch ein Zeitereignis veranlasste Datenbankänderung wird nach den in
5.4. VERWALTUNG VON ZEITEREIGNISSEN
59
Vergangenheit aufgetretenen Zeitereignissen gesucht. Solche (alten) Zeitereignisse werden bearbeitet, falls deren Deadlines noch nicht um sind. Wenn keine
Zeitereignisse aus der Vergangenheit zu bearbeiten sind, wird ein Timer wie
folgt gesetzt:
Der Timer wird zu den nächsten Zeitpunkt gesetzt, wenn ein Zeitereignis
innerhalb einer Woche in der Zukunft erwartet wird. Tritt aber kein Zeitereignis
in einer Woche ein bzw. liegen alle erwarteten Zeitereignisse an Daten über
einer Woche in der Zukunft hinaus, so wird ein Timer für einen Tag gesetzt.
Ablauf jedes Timers wird als das Eintreten eines Zeitereignisses interpretiert.
Wurde sein Timer für ein bestimmtes Datum eingesetzt, das innerhalb einer
Woche eintreten sollte, so werden Trigger gefeuert und bearbeitet. Bei Eintreten
eines inneren Zeitereignisses, d.h. beim Ablauf des für einen Tag eingesetzten
Timers, wird wieder nach einem erwarteten Zeitereignis innerhalb einer Woche
gesucht. wird eins gefunden, so wird ein Timer für das Datum dieses Ereignisses
gesetzt, sonst wird wieder ein Timer für einen weiteren Tag gesetzt.
deadLine:
Zu jedem Zeitereignismuster gibt es eine Deadline , deren Einheit Minute
ist. Das Bild 5.5 zeigt eine Deadline auf der Zeitachse bezüglich eines Zeitpunkte
t1
deadLine
Zeit/Min
Abbildung 5.5: Allgemeine Deadline-Darstellung
,,t1”. Am Zeitpunkt t1 wird das Zeitereignis E erwartet. Zeitpunkt des Bearbeitungsanfangs der durch E gefeuerten Trigger darf nur innerhalb des Zeitintervalls [t1, t1+Deadline] liegen. Der Zweck der Deadline ist, dass beim Ausführen
vorher geforderten Datenänderungen eine gewisse Zeit gebraucht wird. Diese
Bearbeitungszeitadauer spielt bei manchen Regeln eine große Rolle (EchtzeitProblem). Es kann vorkommen, dass Bearbeitung eines Triggers innerhalb 10
Minuten nach dem Eintreten eines Zeitereignisses beginnen soll und nach dem
60
KAPITEL 5. KONZEPT
Ablauf dieser 10-Minuten darf der Trigger nicht mehr bearbeitet werden. Die 5
minütige Mindestgrenze ist zur Sicherheit vorgesehen. Vorsichtshalber soll der
Trigger-Entwickler größere Deadlines einplanen.
Die Deadline ist beschränkt auf dem Interval [5 Minute , ∞).
Deadline wird auch noch für die Erledigung einer weiteren wichtigen Aufgabe eingesetzt. Eine ARTA-Datenbank wird normalerweise nicht ununterbrochen
eingesetzt. Der Einsatz des Systems kann abgebrochen und in einem in unbekannter Zukunft liegenden Zeitpunkt wieder in Anspruch genommen werden,
z.B. eine Datenbank für die Verwaltung der Informationen über die eingeschriebenen Informatik-Studenten an der Universität Bonn. Diese Datenbank wird
nur an Werktagen und zwar nur während der Arbeitszeiten eingesetzt außerhalb dieser Zeiten ist diese Datenbank abgeschaltet. Im Bild 5.6 wurde Einsatz
und der Ruhezustand einer Datenbank im Zusammenhang mit den Zeitereignissen auf einer Zeitachse geschildert.
t1
t2
t3
t4
tn
...
Einsatz
Pause
Einsatz
Pause
Zeit
Abbildung 5.6: Systemeinsatz und Ereignisse
Die Zeitereignissen, die in dem Ruhezustand des System Trigger hätten feuern müssen, werden wie folgt behandelt: Die Ereignisse, deren Deadline noch
nicht vorbei ist, werden berücksichtigt und der Rest wird ignoriert. Ein Trigger,
dessen Ereignismuter ein Zeitereignismuster mit einer Deadline ist, ähnelt der
Regel R2 , die als Beispiel im Abschnitt 2.1 gegeben wurde.
Triggerbearbeitung nach Eintreten eines Zeitereignisses:
Die Trigger, die durch Eintritt von Zeitereignissen gefeuert werden, besitzen
5.4. VERWALTUNG VON ZEITEREIGNISSEN
61
keine Parameter. Deswegen hängt das Ergebnis der Triggerbedingungsauswertung von dem aktuellen Datenbankzustand und von der aktuellen Zeit ab. In
Bedingungen solcher Trigger können z.B. Zeitstempel bestimmter Datensätze
benutzt werden. Durch Vergleichen von Zeitstempeln mit der aktuellen Zeit in
der Bedingungsteil eines Triggers können bestimmte Situationen abgefragt werden. Ist ZTrs die Menge von Triggern, die ein Zeitereignis gefeuert hat, werden
diese Trigger wie folgt bearbeitet:
• Konfliktsituation: Wurden mehrere (mehr als ein) Trigger gefeuret, werden
sie nach ihren Prioritäten sortiert. (#ZT rs > 1)
• Für jeden Trigger T von ZTrs
Bedingung von T auswerten. Ist die Auswertung = ,,True”, setze Aktion
von T als eine Eingabe für den Aufruf von BAS6 ein: BAS(T.action).
6
Vgl. 5.3
62
KAPITEL 5. KONZEPT
Kapitel 6
Implementierung
Im folgenden Kapitel wird die Implementierung von ARTA beschrieben. Dazu
wurde die Programmiersprache VBA benutzt. Bei der Realisierung von Benutzeroberflächen wurden Formulare und deren Ereignisse eingesetzt.
Triggerdaten und Ereignisdaten werden im Laufe des Programms in internen Variablen in Form von Objekten bereitgestellt. Dafür wurden verschiedene
Klassenmodule programmiert, die entweder als einzelne Objekte oder als Auflistungen eingesetzt wurden.
Zunächst werden die Architektur und die Komponenten von ARTA vorgestellt. Danach wird jede Komponente detailliert beschrieben. Anschließend
werden besondere Aspekte erläutert, die in manchen Stellen zur Lösung von
Implementierungsproblemen benutzt wurden.
6.1
Architektur von ARTA
Bei der Architekturplanung wurde auf folgende Punkte geachtet:
• Datenbankänderungen dürfen nicht direkt mit Hilfe von Access Standardkomponenten vorgenommen werden, weil die Ereignisse dabei nicht bemerkt werden können. Für die Kommunikation mit ARTA wurde eine spezielle Oberfläche vorgesehen, die durch den Einsatz eines Formulars realisiert ist. Diese Oberfläche (bzw. Fenster) nennt sich ARTA-Haupfenster.
• Die Existenz eines Werkzeuges, mit dessen Hilfe Trigger bzw. Ereignismuster definiert werden, ist unverzichtbar. Mit diesem Werkzeug sollte
auch die Änderung von Triggern und Ereignismustern möglich sein. In
ARTA werden Trigger bzw. Ereignismuster formularbasiert verwaltet, d.h.
Formulare wurden als Oberflächen so programmiert, dass alle Teile von
Triggern bzw. Ereignismustern eingegeben und geändert werden können.
63
64
KAPITEL 6. IMPLEMENTIERUNG
ARTA
Benutzeroberflächen
SQL
Eingabeformular
11 12 1
10
2
9
3
8
4
7 6 5
BAS
TVS
Befehlsausführungssytem
Trigger und
Eventmuster
Definitionsformular
Timerverwaltungssystem
Regelbasis
Jet DB Engine
Standard-Komponente
von MS-Access
Datenbank
MS-Access
Abbildung 6.1: ARTA und Access
6.2. BENUTZEROBERFLÄCHE
65
• Die Triggerdaten sowie Ereignismusterdaten sollen gesichert werden, es ist
folglich eine Regelbasis notwendig. Die Regelbasis wird in ARTA in Access
Tabellen gespeichert.
• Zur Verwaltung von Zeitereignissen ist eine Uhr bzw. ein darauf aufgebauter Timer notwendig.
• Ein internes System, um Ereignisse zu registrieren und gefeuerte Trigger
zu bearbeiten, ist eine Basis für die Triggerfunktionalität eines aktiven
Datenbankmanagementsystems. Ein solches System ist der Kern jedes aktiven Datenbankmanagementsystems und damit auch von ARTA .
ARTA besteht aus Komponenten, die im Bild 6.1 dargestellt sind. Für die Realisierung von ARTA wurden Access Objekte (Komponenten) benutzt, die in
ARTA als Systemkomponenten gekennzeichnet sind. Die Namen dieser Objekte fangen daher alle mit der Vorsilbe ,,USys ” an. Zusätzlich ist deren Eigenschaft ,,ausgeblendet” aktiviert. ARTA-Objekte können dadurch unsichtbar und
,,nicht mehr direkt modifizierbar” werden.1 ARTA-Komponenten werden in den
folgenden Abschnitten detailliert beschrieben.
6.2
Benutzeroberfläche
Die Implementierung von Benutzeroberflächen wurde mit Hilfe von AccessFormularen und deren Eigenschaften realisiert. Zur Realisierung von Oberflächen wurden Formularereignisse eingesetzt, die besonders geeignet sind, Eingaben zu überprüfen. Mit Hilfe von Formularereignissen wird z.B. die Syntax
einer Triggerdefinition überprüft. Bei einem Syntaxfehler wird eine entsprechende Fehlermeldung ausgegeben. Mit dem Öffnen einer ARTA-Datenbank wird
direkt ein Formular geöffnet, das im Bild 6.3 gezeigt wird. Dieses Formular
heißt ARTA-Hauptfenster. Im ARTA-Hauptfenster sind Buttons (Befehlsschaltflächen) vorgesehen, die dem Benutzer helfen andere Fenster zu öffnen oder den
SQL-Befehl auszuführen. Mit Hilfe des ARTA-Hauptfensters und die darauf
eingebauten Buttons und Tools werden die folgenden Anforderungen erfüllt:
• Durch ,,SQL ausführen” wird ein SQL-Befehl, der in einen dafür vorgesehenen Textfeld eingegeben wurde, an das Befehlausführungssystem gesendet. Wird jede Datenbank-Änderung durch dieses Formular ausgeführt,
so wird das auftretende Ereignis erkannt und die gefeuerten Trigger bearbeitet. Eine Tabelle ist in ARTA dafür vorgesehen, in der SQL-Befehle
(und gegebenenfalls deren Bemerkungen) gespeichert werden. Ein neuer
1
Vgl. Abschnitt 4.4
66
KAPITEL 6. IMPLEMENTIERUNG
Abbildung 6.2: ARTA-Hauptfenster
Datensatz im ARTA-Hauptfenster bedeutet einen Eintrag in dieser Tabelle. Das Speichern von SQL-Befehlen macht nur Sinn, wenn diese Befehle
wiederholend angewendet werden. Das kommt besonders beim Testen von
ARTA in Einsatz.
• Durch ,,SQL löschen” wird der SQL-Befehl und die dazu gehörige Bemerkung gelöscht.
• Durch Mausklick auf dem Button ,,Events” wird ein Fenster geöffnet, in
dem Ereignismuster angezeigt werden. Löschbare Ereignismuster dürfen in
diesem Fenster gelöscht werden. Löschbar sind diejenigen Ereignismuster,
die mit keinem Trigger verknüpft sind.
• Durch ,,Trigger bearbeiten” wird ein Fenster zur Triggerverwaltung geöffnet.
• Durch ,,Show Messages” sieht man die wichtigsten Informationen über
den Triggerbearbeitungsvorgang in einem Fenster.
• Durch ,,Show Logfile” wird ein ausführliches Protokoll vom Einsatz des
ARTA-Systems angezeigt.
Das Fenster, das durch Mausklick auf ,,Trigger bearbeiten” aufgeht, ist eine in ARTA eingebaute Möglichkeit, Trigger und zugehörige Ereignismuster zu
verwalten. Im Bild 6.3 sind zwei Versionen eines Access-Hauptfensters vorgestellt. Eine zeigt das originale Access-Hauptfenster, das z.Z. in Access vorliegt.
6.2. BENUTZEROBERFLÄCHE
67
In diesem Access-Hauptfenster sind Möglichkeiten angeboten, neue Access Objekte und Komponente von bestimmter Art zu definieren und zu verwalten. Die
andere Darstellung ist eine Wunschsform. Das Access-Hauptfenster könnte so
aussehen, wenn Trigger als eine Access-Komponente unterstützt wären. Weil
in Access keine Möglichkeit existiert, Trigger und Ereignismuster zu verwalten,
wird die Trigger- und Ereignismusterverwaltung formularbasiert durchgeführt.
Formulare werden als Benutzeroberflächen (Fenster bzw. Windows) programmiert. In ARTA-Fenstern können Trigger und Ereignismuster definiert,
angezeigt, gelöscht oder modifiziert werden können.
Die gewünschte
Änderung
Trigger
Abbildung 6.3: Hauptfenster von Access
6.2.1
Verwaltung von Triggern
Das Formular zur Verwaltung von Triggern wird ARTA-Triggerfenster genannt.
In Access gibt es die Möglichkeit auszuwählen, in welchem Status (Modus) ein
Formular aufgemacht wird. Die Eigenschaften eines Formulars bestimmen, ob
ein neuer Datensatz eingegeben, der aktuelle Datensatz gelöscht oder geändert
werden darf. Diese Eigenschaften können auch mit Hilfe von VBA-Befehlen
im Formular-Klassenmodul eingestellt werden. Im folgenden Beispiel wird beim
Öffnen eines Formulars eingestellt, dass die Fensterbeschriftung zu ,,Trigger
anschauen!” geändert wird und keine Daten eingegeben, gelöscht sowie geändert
werden dürfen.
68
KAPITEL 6. IMPLEMENTIERUNG
Private Sub Form_Open(Cancel As Integer)
Me.Caption = "Trigger anschauen!"
Me.AllowAdditions = False
Me.AllowDeletions = False
Me.AllowEdits = False
End Sub
Beim Öffnen des Triggerfensters sind die Eigenschaften so eingestellt, dass
keine neuen Trigger eingegeben werden dürfen, und der aktuelle Trigger nicht zu
ändern ist (Modus ,,Trigger anschauen”). Das Triggerfenster wurde im Bild 6.4
in diesem Modus (,,Trigger anschauen”) gezeigt. Mit dem aktuellen Trigger ist
der Trigger gemeint, der im Fenster zu sehen ist. Nach einem Mausklick auf den
entsprechenden Button im Triggerfenster werden Einstellungen des Formulars
so geändert, dass ein neuer Trigger eingegeben bzw. der aktuelle Trigger gelöscht
oder geändert werden kann. Mausklicks auf Buttons haben dieselben Funtionalitäten wie die entsprechenden Befehle, die in SQL3 benutzt werden, z.B. Create
Trigger, Delete Trigger, Modify Trigger. Ob ein Trigger aktiv oder nicht aktiv
ist, wird durch Markierung des hierzu vorgesehenen Feldes eingestellt. Aktiv
sind diejenigen Trigger, die beim Auftritt eines Ereignisses berücksichtigt werden. Nicht aktive Trigger (passive Trigger) werden ignoriert und sind nur intern
gespeichert. Trigger, die fehlerhaft sind, werden als passiv gespeichert, wodurch
eine korrekte Triggerbearbeitung garantiert wird.
Bei Textfeldern mit langen Texten kann der Text mittels speziell dafür vorgesehenen Buttons oder Maus-Doppelklick in einem größeren Fenster angesehen
und bearbeitet werden. Dies ist sehr wichtig bei Triggerbedingung und Triggeraktion, die im Triggerfenster nur begrenzten Platz haben und manchmal (bei
langen Texten) nicht vollständig angezeigt werden. Diese Technik, lange Texte in einem separaten Fenster zu bearbeiten, ist in jedem Fenster von ARTA
vorgesehen, bei dem Textfelder für lange Texte existieren.
6.2.2
Verwaltung von Ereignismustern
Ereignismuster werden gleichzeitig mit Triggern erzeugt und modifiziert. Das
Löschen eines Ereignismusters wird in einem separaten Fenster durchgeführt,
das durch Maus-Klick auf dem entsprechende Button im ARTA-Hauptfenster
(Events) geöffnet wird. Das Bild 6.5 zeigt dieses Fenster, in dem die Ereignismuster angeschaut und gelöscht werden können. Das Fenster heißt das ARTA-
6.2. BENUTZEROBERFLÄCHE
Abbildung 6.4: Das Trigger-Fenster im Modus ,,Trigger anschauen”
69
70
KAPITEL 6. IMPLEMENTIERUNG
Ereignismusterfenster. Im Ereignismusterfenster können vorhandene Ereignis-
Abbildung 6.5: ARTA-Ereignis-Muster-Fenster
muster nur angeschaut und gelöscht werden. Dieses Fenster hat nur diese Funktionalität und sonst keine.
Beim Löschen eines Triggers wird das Ereignismuster dieses Triggers ,,nicht mitgelöscht”.
Das Löschen eines Triggers wird im Triggerfenster durchgeführt und das
Löschen eines Ereignismusters muss extra im Ereignismusterfenster durchgeführt
werden. Das mag vielleicht ein bisschen lästig erscheinen, macht aber Sinn, wenn
man beachtet, dass ein Ereignismuster mit mehreren Triggern verknüpft sein
darf. Ein Ereignismuster darf nur dann gelöscht werden, wenn mit ihm kein
Trigger mehr verknüpft ist. Im Ereignismusterfenster wird beim Anzeigen jedes Ereignismusters seine Löschbarkeit automatisch geprüft und (informativ)
angezeigt. Im Ereignismusterfenster sind bestimmte Buttons eingebracht worden, mit deren Hilfe das aktuelle Ereignismuster (wenn es löschbar ist) bzw. alle
löschbaren Ereignismuster gelöscht werden können.
6.3
Speichern von Regeln
Die Menge aller Trigger heißt Regelbasis, deren Daten gesichert werden müssen.
Dafür sind zwei Tabellen in ARTA vorgesehen: In der Tabelle ,,USys trigger”
werden Daten von Triggern gespeichert, in der Anderen ,,USys event” werden
Daten von Ereignismustern gespeichert. Weil die Name dieser Tabellen mit
6.3. SPEICHERN VON REGELN
71
,,USys” anfangen, werden diese Tabellen als Access Systemkomponente interpretiert und können unsichtbar werden2 . Diese Tabellen sind miteinander durch
eine Access-Beziehung verknüpft. Die Eigenschaften dieser Beziehung sind so
eingestellt worden, dass ein Ereignismuster mit mehreren Triggern verbunden
werden darf.
Abbildung 6.6: Beziehung zwischen der Tabelle von Triggern mit der Tabelle
von Ereignismutern
USys trigger
Der Primärschlüssel besteht in dieser Tabelle aus zwei Felder: ,,trigger id”
und ,,trigger name”, wobei ersteres ,,trigger id” nur als eine interne Indentifikatiosnummer einzusehen ist. Dagegen sorgt ,,trigger name” dafür, dass keine
zwei Trigger mit dem gleichen Namen versehen werden. Damit wird die Eindeutigkeit von Triggernamen gewährleistet. Die Priorität eines Triggers wird unter
dem Feld ,,trigger priority gespeichert. Damit eine sichere Priorität garantiert
wird, wurde das Feld so eingestellt, dass
1. sein Inhalt nur eine natürliche Zahl größer als ,,0” sein darf,
2. keine zwei Datensätze mit gleichem Inhalt erlaubt sind,
2
s. Unterabschnitt: 4.4
72
KAPITEL 6. IMPLEMENTIERUNG
3. und das Feld nicht leer sein darf.
Das Feld ,,trigger event name” ist in dieser Tabelle ein Fremdschlüssel, dessen Inhalt nur ein Element aus der Menge der vorhandenen Ereignismusternamen sein darf. Doppelte Daten dürfen bei diesem Feld vorkommen, damit
mehrere Trigger mit einem Ereignismuster verbunden werden können. Weitere
Felder in dieser Tabelle beinhalten Teilinformationen eines Triggers. z.B. Bedingung, Aktion, Aktivität, . . . .
USys event
Mit ,,event name” werden Ereignismuster in dieser Tabelle eindeutig bestimmt.
Der Primärschlüssel besteht auch in dieser Tabelle aus zwei Feldern: ,,event id”
und ,,event name”. Alle drei Ereignismustertypen werden in dieser Tabelle zusammen gespeichert. Der Typ eines Ereignismusters wird durch den Inhalt des
Feldes ,,event type” gegeben. In diesem Feld ist dementsprechend nur ein Eintrag aus {time event atOnce, time event periodic und modify event} möglich.
Nachdem der Ereignismustertyp bestimmt worden ist, werden die für diesen
Typ relevante Daten berücksichtigt.
6.4
Klassen, Module und Objekte von ARTA
In ARTA wurden Module und Klassenmodule programmiert, um die Informationen von Triggern und Ereignismustern für die Erledigung von weiteren Aufgaben bereitzustellen. Diese Aufgaben sind Ereigniserkennung, die Bearbeitung
von Triggern eines aufgetretenen Ereignisses, die Berechnung des nächsten Termins für den Timer und das Setzen des Timers.
6.4.1
Klassenmodule
In ARTA wurden folgende Klassenmodule programmiert:
USys clsTrigger:
Unter einem Objekt dieser Klasse werden Daten eines Triggers gespeichert.
USys clsTriggers:
Ein Objekt dieser Klasse ist eine Auflistung von Triggern. Ein neuer Trigger
wird an der richtigen Stelle der Auflistung so hinzugefügt, dass Trigger automatisch nach Prioritäten sortiert sind. So hat das erste Element eines Objekts
dieser Klassen immer die höchste Priorität (niedrigste Prioritätszahl).
6.4. KLASSEN, MODULE UND OBJEKTE VON ARTA
73
USys clsModifyEvent:
Ein Objekt dieser Klasse beinhaltet alle Trigger (ein Objekt der Klasse
,,USys clsTriggers”), die beim Auftritt eines bestimmten Änderungsereignisses
gefeuert werden. Das Ereignis wird durch eine interne Variable dieser Klasse
,,mstr eventKey” identifiziert, die aus DML-Befehl und Tabellenname (<DML>
<table name>) besteht. Dieser Schlüssel wird erst in einer Auflistung von der
Klasse USys clsModifyEvents benutzt.
USys clsModifyEvents:
Ein Objekt dieser Klasse ist eine Auflistung, deren Elemente Objekte der Klasse ,,USys clsModifyEvent” sind. In der Auflistung sind die Ereignismuster und
die mit ihnen verbundenen Trigger so eingefügt, dass alle Trigger mit gleichem
,,mstr eventKey” ((<DML><table name>)) unter einem Element zusammengefasst sind. Mit dem Aufruf der folgenden Prozeduren dieser Klasse werden
alle Trigger (bzw. alle Beforetrigger und Aftertrigger) zurück gegeben, die beim
Auftritt eines Änderungsereignisses ,,strDMLCommon” auf die Tabelle ,,strTablename” gefeuert werden müssen:
Public Function getTriggers( _
ByVal strDMLCommon As String, _
ByVal strTablename As String) As USys_clsTriggers
Public Function getBeforeTriggers( _
ByVal strDMLCommon As String, _
ByVal strTablename As String) As USys_clsTriggers
Public Function getAfterTriggers( _
ByVal strDMLCommon As String, _
ByVal strTablename As String) As USys_clsTriggers
USys clsTimeEvent:
Ein Objekt dieser Klasse beinhaltet Informationen über ein Zeitereignismuster.
Der Typ des Zeitereignisses wird in die interne Variable ,,mstr event type” eingesetzt, und je nach Zeitereignistyp werden spezielle Informationen in andere
Variablen eingesetzt.
USys clsTimeEvents:
Aus dieser Klasse werden Objekte instantiiert, die als Auflistung von Zeitereignisobjekten benutzt werden. Jedes Element einer solchen Auflistung besteht aus
Informationen über ein Zeitereignismuster und den Triggern, die beim Auftreten dieses Zeitereignisses gefeuert werden müssen. Wie erwähnt können mehrere
74
KAPITEL 6. IMPLEMENTIERUNG
Trigger ein gemeinsames Ereignismuster besitzen.
USys clsSetOfTimeEvents:
Ein Objekt dieser Klasse ist eine Auflistung von Objekten der Klasse
USys clsTimeEvents. Jedes Objekt der Klasse USys clsSetOfTimeEvents besteht aus Triggern, die an einem bestimmten Zeitpunkt gefeuert werden müssen.
Diese Trigger können verschiedenen Ereignismuster angehören, die aber alle
ein gemeinsames (,,absolutes”) Zeitereignis beschreiben. Mit Hilfe dieser Klasse
werden die zwei verschiedenen Zeitereignistypen ,,periodisch und absolut” unter
einem Objekt bereitgestellt. Die Prozedur ,,ChangeStatus()” ist in der Klasse
USys clsTimeEvent programmiert. Eine Ausführung dieser Prozedur ändert die
Eigenschaften des Zeitereignismusters entsprechend dem Typ: Ein absolutes Zeitereignismuster wird als erledigt ,,beDone” vermerkt und für ein periodisches
Zeitereignismuster wird der nächste Termin berechnet.
USys clsExecute:
Diese Klasse beinhaltet die Prozedur ,,Public Sub ExecuteSQL Statement (ByVal strAction As String)”. Diese Prozedur ist sozusagen das Herz des Befehlsausführungssystems (BAS). ,,strAction” ist der Eingabeparameter, der entweder
ein direkter SQL-Befehl aus dem ARTA-Hauptfenster oder der Aktionsteil eines
Triggers sein kann. Diese Prozedur wird im Abschnitt 6.5 genauer untersucht.
USys clsTriggerExecutionContext:
Eine Instanz dieser Klasse beinhaltet der sogenannte Trigger execution Context
(TEC). In TEC werden bezüglich eines SQL-Ausdruckes folgende Informationen gespeichert: die betroffene Tabelle, der Eereinistyp (DELETE, INSERT
oder UPDATE), die Transition. Die Transition besteht aus zwei temporären
Tabellen NEW TABLE und OLD TABLE. Die Daten der Transitionstabellen
werden in zwei internen Variablen vom Typ ,,Recordset” gespeichert (Private
rstOld As DAO.Recordset und Private rstNew As DAO.Recordset). Mit Hilfe
von Methoden ,,MoveNextRow, MovePrevRow, MoveFirstRow, MoveLastRow”
können diese Variablen durchlaufen werden.
USys clsParser:
Diese Klasse ist hauptsächlich dafür gedacht, einen SQL-Ausdruck zu analysieren (parsern). Ein SQL-Ausdruck kann sehr kompliziert werden. Es ist sehr
aufwendig, einen Parser für die SQL-Standard-Ausdrücke zu programmieren.
Die Programmierung eines richtigen SQL-Parsers geht über den Rahmen dieser
Arbeit hinaus. Deswegen sind hier nur eingeschränkte SQL-Ausdrücke erlaubt.
Prozeduren in dieser Klasse setzten folgende Syntax für SQL-Ausdrücke voraus:
INSERT INTO Table . . . ,
6.4. KLASSEN, MODULE UND OBJEKTE VON ARTA
75
DELETE [Table.*] FROM Table . . . ,
UPDATE Table . . . .
Zusätzlich sollen diese Ausdrücke mit dem Access SQL-Dialekt übereinstimmen.
Deswegen ist es zu empfehlen, SQL-Ausdrücke in einer Access Abfrage (QBEMethode3 ) herzustellen. Eine weitere Einschränkung besteht in der Benennung
der Tabellen. Obwohl in Access selbst fast jedes Zeichen für die Benennung der
Access-Komponenten erlaubt ist, sollen die Access-Namen in ARTA nur aus
Zeichen der Menge {a,b,. . . ,z,A,B,. . . , } bestehen.
USys clsTimer und USys clsTimers:
Mit Hilfen dieser Klassen wird die Möglichkeit geboten, mehrere Timer zu setzen
und zu verwalten.
6.4.2
Module und Objekte
Module beinhalten als ,,Global” deklarierte Prozeduren, die direkt aufgerufen
werden können. Es ist also für den Aufruf von globalen Prozeduren in einem
Modul kein Objekt notwendig. Deswegen können sie an jeder Stelle in VBA
bzw. Access vorkommen, wie z.B. in Modulen, Klassenmodulen, Abfragen, Formularen, Makros. In ARTA wurden zwei Module definiert:
Das Modul: USys FreeFunctionsARTA
In diesem Modul sind einige Funktionen programmiert, die vor allem für die
Nutzung in Triggerteilen (Triggerbedingung und Triggeraktion ) vorgesehen
sind. Sollten weitere Funktionen zur Erledigung bestimmter Aufgaben notwendig sein, können sie hier einprogrammiert werden.
Der Befehl AbortEvent() bricht die Ausführung des aktuellen SQL-Ausdrucks
ab. Dieser Befehl sollte in der Aktion eines Beforetriggers eingegeben werden,
wenn ein SQL-Ausdruck unter einer bestimmten Bedingung nicht ausgeführt
werden darf. AbortAll() bricht die Ausführung von Änderungsbefehle in der aktuellen Transaktion ab und setzt alle Änderungen zurück.
WarningByEmail(SQL, changeCommand) funktioniert wie folgt:
• Durch die SQL-Abfrage ,,SQL” werden Email-Adressen aus einer geeigneten Tabelle ausgewählt. Dabei ist zu beachten, dass jeweils das erste Feld
in der SQL-Abfrage als Email-Adresse auszuwählen ist.
3
Vgl. Abschnitt 4.1, Paragraph ,,Abfragen und SQL-Befehle”
76
KAPITEL 6. IMPLEMENTIERUNG
• In einem Warnungsfenster wird der Benutzer darauf hingewiesen, Nachrichten an diese Email-Adressen zu schicken.
• Durch ,,changeCommand” wird eine Änderung an einem bestimmten Feld
der ausgewählten Datensätze dieser Tabelle angezeigt. ,,changeCommand”
hat die Syntax ,,<feldname>=<value>”.
Mit einer geeigneten Modifikation (Umprogrammierung) kann diese Prozedur so
verwendet werden, dass das Email-Programm vom Betriebsystem automatisch
ausgeführt wird und Emails verschickt werden.
DatumAdd(number, Interval, date) addiert ,,nummber”-viele ,,Intervale” zu
,,date” und gibt das Ergebnis zurück. ,,nummber” ist eine natürliche Zahl, ,,Intervale” ist ein Element aus der Menge {’Minute’, ’Stunde’, ’Tag’, ’Woche’,
’Monat’, ’Quartal’, ’Jahr’} und ,,date” ist eine Datumangabe.
DatumAb(dtefrom, Interval, dteuntil) gibt der Zeitabstand zwischen ,,dtefrom” und , ,,dteuntil” in der Einheit ,,Interval” zurück.
Das Modul: USys ToolsAndPublicsARTA
Auf diesem Modul wurden die globale Variablen (Objekte) und Funktionen abgelegt, die zur Triggerbearbeitung benutzt werden. Im folgenden sind die wichtigsten Objekte aufgelistet:
Unter der Auflistung allTimeEvents (As USys clsSetOfTimeEvents) sind alle Zeitereignismuster abgelegt. Die Zeitereignismuster sind in der Auflistung
nach Datum, an dem das zugehörige Zeitereignis erwartet wird, sortiert. Dabei
entspricht das erste erwartete Zeitereignis dem erste Zeitereignismuster in der
Auflistung.
Unter der Auflistung allModifyEvents (As USys clsModifyEvents) sind alle Änderungsereignismuster abgelegt. Jedes Objekt dieser Auflistung ist eine
Gruppe von Triggern, die beim Auftreten eines bestimmten Änderungsereignisses an einer bestimmten Tabelle gefeuert werden müssen.
allTimers (As USys clsTimers) beinhaltet alle gesetzten Timer in ARTA.
Sollte in einer Access-Anwendung ein Makro mit dem Namen ,,Autoexec”
erstellt worden sein, wird dieses Makro beim Start der Anwendung (beim Öffnen dieser Datenbank unter Access) automatisch ausgeführt. Diese Eigenschaft
wurde in ARTA benutzt, um beim Start interne Variablen (Objekte) zu initialisieren. Im Makro ,,Autoexec” wird die Prozedur ,,Public Function initSystem()”
6.5. BEFEHLSAUSFÜHRUNGSSYSTEM
77
ausgeführt. In der Prozedur ,,initSystem()” werden o.g. Objekte (Variablen bzw.
Auflistungen) deklariert und bereit gestellt.
6.5
Befehlsausführungssystem
Der Einsatz der ,,Rekursion” ist nach der in Abschnitt 5.3 beschriebenen Triggerbearbeitungssemantik unvermeidbar. Nach dem Aufruf einer rekursiven Prozedur ruft sie sich wieder auf und stellt der neuen Instanz die neuen Ergebnisse
zur Verfügung. Zusätzlich soll ein bestimmtes Ergebnis existieren, nach dem die
Prozedur sich nicht mehr aufrufen soll. Durch dieses Ergebnis wird das Terminieren der Prozedur garantiert.
Die Rekursion für die Triggerbearbeitung findet in der Prozedur ,,ExecuteSQL Statement” statt. Im folgenden wird eine stark vereinfachte Version dieser
Prozedur angezeigt. Viele Zwischenschritte und Anweisungen wurden nicht angezeigt, damit der Aspekt der Rekursion besser sichtbar wird.
01)Public Sub ExecuteSQL_Statement(ByVal strAction As String)
02)
03) \\Fuer jeden Trigger von Beforetriggern
04) For Each Tr In beforeTrs
05)
Tr.Condition = True => Call ExecuteAction(T.Action)
06) Next Tr
07)
08) \\Die Befortrigger sind bis hierhin alle abgearbeitet,
09) \\und die "eigentliche Ausfuehrung des SQL"-Ausdruckes
10) \\findet hier statt.
11) Call ExecuteAction(strAction)
12)
13) \\Fuer jeden Trigger in Aftertriggern
14) For Each Tr In afterTrs
15)
If Tr.Condition = True Then
16)
Call ExecuteSQL_Statement(T.Action)
17)
End If
18) Next Tr
19)End Sub
Die Beforetrigger werden zwischen den Zeilen ,,03)” und ,,06)” abgearbeitet. Für jeden Beforetrigger gilt: Ist dessen Bedingung erfüllt, wird die Funktion
,,ExecuteAction(Triggeraktion)” aufgerufen. An der Zeile ,,11)” wird der SQLAusdruck aufgerufen. Die Aktion jedes Aftertriggers, dessen Bedingung erfüllt
78
KAPITEL 6. IMPLEMENTIERUNG
ist, wird als Eingabeparameter für den Aufruf der selben Prozedur in der Zeile
,,16)” benutzt und damit ausgeführt. Zu jeden Aftertrigger wird die Prozedur
also nochmal aufgerufen. Jede aufgerufene Prozedur muss warten, bis alle Unterprozeduren mit der Bearbeitung fertig sind.
Die Terminierung dieser Prozedur ist aus der Sicht der Rekursion garantiert,
d.h. die Bedingung für die Beendigung der Rekursion sind in der ,,For Each”Anweisung (Zeile ,,14)”) gegeben. Wenn alle Aftertrigger abgearbeitet sind, ist
die Rekursion zu Ende. Die Tiefe der Rekursion ist jedoch unbekannt. Die Terminierung der Prozedur ist allerdings aus Sicht der Triggerbearbeitung nicht
garantiert. Wenn z.B. der SQL-Ausdruck S Aftertrigger {T1 , T2 , . . . , Tn } feuert
und der Aktionsteil des Triggers Ti ∈{T1 , T2 , . . . , Tn } derselbe SQL-Ausdruck
S ist, kommt eine endlose Schleife zustande.4
Die endgültige Ausführung eines Befehls findet in der Funktion ,,ExecuteAction” statt. Diese Funktion sieht wie folgt aus:
Private Sub ExecuteAction(ByVal strCommand As String)
If strCommand = "" Then
LogFileOutput strCommand & "Keine Aktion!!!!!!!"
ElseIf isSQL(strCommand) Then
’ SQL-Ausdruck
CurrentDb.Execute strCommand
Else
Eval (strCommand)
End If
End Sub
Mit dem Befehl ,,CurrentDb.Execute” können nur SQL-Ausdrücke ausgeführt
werden. Deswegen wird die Ausführung von ,,nicht SQL-Ausdrücken”, z.B. der
Aufruf von Funktionen, dem VBA-Befehl ,,Eval” überlassen.
Ein Trigger mit leerem Aktionsteil wird zwar jedes Mal beim Eintritt
seines Ereignisses gefeuert, führt jedoch keine Aktionen aus und verursacht deswegen keine Laufzeitfehler.
Die rekursive Funktion ,,ExecuteSQL Statement” wird aus der Prozedur
,,doAction(str)” gestartet. Im folgenden wird ,,doAction(str)” angezeigt. In dieser Prozedur beginnt erst durch ,,wks.BeginTrans” eine Transaktion und danach
4
Vgl. [?], S51-67
6.6. FEHLERBEHANDLUNG
79
wird die rekursive Funktion ,,ExecuteSQL Statement” aufgerufen. Ein Fehler,
der in ,,ExecuteSQL Statement” bzw. ,,ExecuteAction” eintritt, wird an ,,doAction” weitergeleitet und die Transaktion wird hier mit ,,wks.Rollback” zurückgerollt. Tritt kein Fehler ein, so werden die Änderungen mit ,,wks.CommitTrans”
festgeschrieben.
Public Sub doAction(ByVal str As String)
Dim wks As DAO.Workspace
Set wks = DBEngine.Workspaces(0)
wks.BeginTrans
On Error GoTo Err_doAction
Dim clsTExecute As New USys_clsExecute
clsTExecute.ExecuteSQL_Statement (str)
wks.CommitTrans
Exit_doAction:
Exit Sub
Err_doAction:
wks.Rollback
Resume Exit_doAction
End Sub
Die Prozedur ,,doAction(str)” wird an folgenden Stellen aufgerufen:
1. doAction(SQL S) wird im ARTA-Hauptfenster aufgerufen, wenn ein SQLAusdruck S an der Datenbank anzuwenden ist.
2. Beim Eintritt eines Zeitereignisses werden alle Trigger separat nacheinander in einer Schleife überprüft. Ist die Bedingung eines Triggers erfüllt, so
wird die Prozedur doAction(Triggeraktion) aufgerufen.
Die Auswertung von Bedingungen und die Parameterübergabe an Triggeraktionen werden extra in Unterabschnitt 6.7.1 beschrieben.
6.6
Fehlerbehandlung
In der ARTA-Triggerbearbeitung gibt es keine Kompilierungsfehler. Bei ARTA
wurde versucht, die Syntax eines Triggers und des dazugehörigen Ereignismu-
80
KAPITEL 6. IMPLEMENTIERUNG
sters bei der Definition zu überprüfen. Am Ende dürfen nur die Trigger aktiviert sein und später gefeuert werden, die syntaktisch korrekt definiert sind.
Die Sytaxprüfung wird in dem Fenster durchgeführt, in dem der Trigger und
das Ereignismuster verwaltet werden. Deswegen ist eine korrekte Syntax jedes
Triggers garantiert, bevor er zum Einsatz kommt. Logische Fehler sind in der
ARTA-Triggerbearbeitung wie bei jeder Programmiersprache nicht ohne weiteres zu finden. Sie haben negative Auswirkungen auf das Endergebnis. In ARTA
ist kein Debugger eingebaut, da der Bau eines Debuggers sehr aufwendig ist
und über den Umfang dieser Arbeit hinausgeht. Deshalb sollten Trigger sehr
aufmerksam definiert bzw. geändert werden.
Ein Laufzeitfehler kann bei der ARTA-Triggerbearbeitung in folgenden Situationen vorkommen:
• Auswertungsfehler können bei der Auswertung einer Triggerbedingung
eintreten.
• Befehlsausführungsfehler treten bei der Ausführung eines Befehls auf.
Diese Fehler sind selbst in zwei Untergruppen zu teilen:
– SQL-Eingabefehler tritt bei der Ausführung der SQL-Eingabe in der
Anfangsphase im ARTA-Hauptfenster auf.
– Innen-Befehlsfehler haben sich in den Aktionsteil eines Triggers eingeschlichen und treten erst dann auf, wenn der Trigger gefeuert wird
und die Auswertung seiner Bedingung ”True” zurück gibt und seine
Aktion ausgeführt wird.
Auswertungsfehler werden so behandelt, als ob die Auswertung einer Triggerbedingung ”False” zurückgibt. Eine falsche (unsinnige) Bedingung für einen
Trigger bewirkt, dass der Aktionsteil dieses Triggers nie ausgeführt werden kann.
Deswegen ist es sehr wichtig Triggerbedingungen mit großer Aufmerksamkeit zu
formulieren.
Eine leere Trigger-Bedingung ist eine sinnvolle Bedingung und wird
immer als True interpretiert.
Die SQL-Eingabefehler ist am einfachsten zu behandeln. Solche Fehler werden sofort nach dem Maus-Klick auf den entsprechenden Button im ARTAHauptfenster erkannt. Es wird direkt eine Access-Fehlermeldung ausgegeben,
die dem Benutzer auf den Fehler hinweist. Dabei ist zu beachten, dass im ARTAHaptfenster nur die SQL-Befehle der Form DELETE . . . , INSERT . . . und UPDATE . . . erlaubt sind.
6.7. BESONDERE ASPEKTE
81
Innen-Befehlsfehler treten erst im Laufe einer Ausführung ein. Diese Fehler
werden durch die Ausführung einer Triggeraktion verursacht.
beim Eintreten eines Innen-Befehlsfehlers wird die SQL-Bearbeitung
abgebrochen und alle Datenbankänderungen werden zurückgesetzt.
Ein SQl-Befehl kann eine Kette von voneinander abhängigen Datenbankänderungen zur Folge haben. Alle Datenbankänderungen dieser Kette müssen vorgenommen werden, damit das Ziel der Definitionen der daran beteiligten Trigger
erreicht wird. Datenbankänderungen, die durch einen SQL-Befehl vorgenommen werden, werden in einer Transaktion zusammengefasst. Dadurch werden
alle Änderungen als eine Einheit (alle oder keine) durchgeführt. Die InnenBefehlsfehler können auch aufgrund von Integritätsverletzungen auftreten. Die
referentielle Integrität kann in Access durch Beziehungen und deren Eigenschaften definiert werden. Um solche Fehler zu vermeiden, sollten Integritäten und
Integritätsprüfungen nicht durch Access-Beziehungen sondern durch ARTATrigger definiert werden.
Im Code der Prozedur ,,doAction” (Im Abschnitt: 6.5) wurden VBA-Methoden der Transaktionsverwaltung und der Fehlerbehandlung genutzt und miteinander kombiniert. Durch diese Kombination wird der erste Innen-Befehlsfehler
gefangen und an die Funktion ,,doAction” zurückgegeben.
6.7
6.7.1
Besondere Aspekte
Trigger Execution Context
Bei einem Trigger, der durch ein Änderungsereignis gefeuert wird, können Parameter für die Inhalte der betroffenen Tabelle bzw. der betroffenen Zeilen der
Tabelle definiert werden. Diese Parameter können im Bedingungs- sowie im
Aktionsteil des Triggers vorkommen. Dazu müssen die Änderungen des SQLAusdrucks, durch dessen Ausführung ein Änderungsereignis eintritt und die
Trigger gefeuert werden, vor der eigentlichen Ausführung bestimmt werden.
Um diese Änderungen vorher zu bestimmen, müssen zwei temporäre Tabellen
erzeugt werden. Die erste temporäre Tabelle enthält die betroffenen Datensätze
vor der SQL-Ausführung und die andere temporäre Tabelle die betroffene Datensätze nach der SQL-Ausführung auf der Originaltabelle. Die temporären Tabellen werden intern erzeugt und nach einer Triggerbearbeitungssitzung automatisch gelöscht. Es ist lediglich ein Lesezugriff auf Daten der temporären
Tabellen erlaubt. Vor einer Bedingungsauswertung, sowie bei der Bereitstellung
82
KAPITEL 6. IMPLEMENTIERUNG
eines Aktionsteils sollten die temporären Tabelle vorhanden sein.
Bei einem Statement-Level-Trigger ist ein Datenzugriff auf die gesamten Informationen dieser Tabellen relevant und bei einem Row-Level Trigger sind die
einzelnen Datensätze interessant. Um einzelne Datensätze zu lesen, müssen diese Tabellen durchlaufen werden. Die Klasse ,,USys clsTriggerExecutionContext”
(Klassenmodul) wurde für die Erledigung der o.g. Aufgaben vorgesehen. Ein Objekt dieser Klasse wird bei jedem Aufruf der Funktion ,,ExecuteSQL Statement
(strAction)” erzeugt, falls ,,strAction” ein SQL-Ausdruck ist und Trigger feuert.
Ein Objekt dieser Klasse wird wie folgt erzeugt:
Dim tec As New USys clsTriggerExecutionContext.
Nach Erzeugung dieses Objektes stehen seine Methoden zur Verfügung. Mit
tec.initTEC (strAction) werden die zwei temporäre Tabellen auf das aktuelle
Verzeichnis (auf dem Verzeichnis, in dem die Datenbank gespeichert ist) gespeichert. Die temporären Tabellen haben genau die gleiche Struktur wie die
Originaltabelle. Um diese Tabelle herzustellen, wird auch die Technik von ,,Tabellenerstellungsabfragen” eingesetzt. Eine Tabellenerstellungsabfrage hat die
Form ,,SELECT <feldliste> INTO neueTabellenname FROM alteTabellenname WHERE bedingung;”.
Die Herstellung von temporären Tabellen wird wie folgt durchgeführt:
• bei INSERT:
1. newTmp := Orgtable, dabei wird der Befehl ,,DoCmd.CopyObject”
eingesetzt.
2. Löschen aller Datensätze aus newTmp mit dem Befehl
,,CurrentDb.Execute ’DELETE * From ’ & newTmp”
3. Iem Original-SQL wird der Tabellenname ,,Orgtable” durch ,,newTmp” ersetzt. Damit entsteht ein neuer SQL-Ausdruck, ,,sqltmp”.
4. ,,sqltmp” ausführen.
Damit besteht ,,newTmp” aus den neuen Datensätzen, die mit der Ausführung des SQL-Ausdrucks zur ,,Orgtable” hinzugefügt werden. Bei INSERT
hat die ,,oldTmp” keine Daten.
• Bei DELETE soll der Befehl ,,CurrentDb.Execute ’SELECT * into ’ &
oldTmp & ’ From ’ & Orgtable & ’ ’ & getWhere” ausgeführt werden, wobei der WHERE-Teil mit Hilfe von Prozeduren der Klasse ,,USys clsparser”
aus dem Original-SQL berechnet wird. Durch die Ausführung dieses Befehls wird eine Tabelle Namens ,,oldTmp” erstellt, die genau diejenigen
6.7. BESONDERE ASPEKTE
83
Datensätze besitzt, die aus der Originaltabelle gelöscht werden sollen. Bei
,,DELETE” ist die temporäre Tabelle ,,newTmp” leer.
• Bei UPDATE:
1. oldTmp := Orgtable mit dem Befehl ,,DoCmd.CopyObject”.
2. in oldTmp werden alle nicht betroffenen Datensätze gelöscht, damit
in dieser Tabelle nur die betroffenen Datensätze im alten Zustand
übrig bleiben. Dabei werden die Methoden der Klasse ,,USys clsparser”
benutzt, um den WHERE-Teil vom Original-SQL zu berechnen und
zu negieren.
3. newTmp := oldTmp mit dem Befehl ,,DoCmd.CopyObject”. Nun
sind beide temporären Tabellen identisch.
4. Im Original-SQL wird der Tabellenname ,,Orgtable” durch ,,newTmp” ersetzt. Damit entsteht ein neuer SQL-Ausdruck, ,,sqltmp”.
5. ,,sqltmp” ausführen.
Die temporären Tabellen werden unter zufällig erzeugten Namen gespeichert.
Der Name von oldtmp hat die Vorsilbe ,,USys ARTA OLD ” und der Name
von newtmp hat die Vorsilbe ,,USys ARTA NEW ”. Nach der Vorsilbe kommt
eine zufällige Zeichenkette, bestehend aus zehn Buchstaben gefolgt von einer
zufälligen (achtstelligen) Zahl. Dabei werden die VBA-Befehle ,,Randomize”
und ,,Rnd” eingesetzt. Diese Namen werden nach Beendigung einer Triggerbearbeitungssitzung in der Funktion ,,doAction” gelöscht. Zur Sicherheit wird
beim Löschen überprüft, ob der Name der o.g. Form entspricht, damit keine
wichtige Tabellen gelöscht werden.
Durchlaufen der Transitionen
In einem Objekt der Klasse ,,USys clsTriggerExecutionContext” sind zwei interne Variablen zuständig für die Bereitstellung der betroffenen Datensätze für
den Einsatz in den Triggerteilen. Diese Variablen sind vom Typ ,,Recordset”
der Schnittstelle ,,DAO” und werden wie folgt definiert:
Private rstOld As DAO.Recordset
Private rstNew As DAO.Recordset
Nachdem die temporären Tabellen hergestellt sind, werden die betroffenen
Datensätze werden in diese Variablen wie folgt übernommen:
Set rstNew = CurrentDb().OpenRecordset(USys ARTA NEW . . . )
Set rstOld = CurrentDb().OpenRecordset(USys ARTA OLD . . . )
Mit Hilfe von Methoden, die in dieser Klasse programmiert sind, wie ,,MoveNextRow”, ,,MovePrevRow”, ,,MoveFirstRow”, ,,MoveLastRow” werden die
84
KAPITEL 6. IMPLEMENTIERUNG
Recordset-Variablen durchlaufen.
Mit Hilfe der Methode ,,makeAction” werden alle Parameter im Aktionsteil
eines Triggers durch die Inhalte von temporären Tabellen ersetzt. Dazu werden
Methoden der Klasse ,,USys clsparser” sowie ,,USys clsTriggerExecutionContext”
benutzt.
Eine weitere wichtige Methode dieser Klasse ist ,,ConditionValue”. Diese
Methode gibt ja/nein zurück, d.h. dass die Auswertung der Triggerbedingung
durch diese Methode erledigt wird. In dieser Methode werden Parameter der
temporären Tabellen berechnet und in der Triggerbedingung eingesetzt. Nach
dem Einsetzen der Inhalte von Parameter wird das Ergebnis mit Hilfe des Befehls ,,ConditionValue=CBool(Eval(CStr(strconditionText)))” ausgewertet, wobei der Triggerbedingungstext nach dem Parametereinsatz ,,strconditionText”
ist.
6.7.2
Timer
Timer wurden in ARTA mit Hilfe von API-Schnittstelle realisiert. Dabei wurden
zwei Prozeduren aus der DLL-Datei ,,User32.dll” eingesetzt. Zunächst müssen
diese Prozeduren wie folgt deklariert werden:
Private Declare Function SetTimer _
Lib "User32" _
( _
ByVal Hwnd As Long, _
ByVal nIDEvent As Long, _
ByVal uElapse As Long, _
ByVal lpTimerFunc As Long _
) _
As Long
Private Declare Function KillTimer _
Lib "User32" _
( _
ByVal Hwnd As Long, _
ByVal nIDEvent As Long _
) _
As Long
Mit dem Aufruf der Prozedur ,,SetTimer” wird ein Timer gesetzt, der alle
,,uElapse”-Millisekunden ,,periodisch” eine Rückruf-Funktion der Adresse ,,lp-
6.7. BESONDERE ASPEKTE
85
TimerFunc” aufruft. Durch den Aufruf der Prozedur ,,KillTimer” wird der Timer mit der Idenditätsnummer ,,nIDEvent” abgebrochen. Der Einsatz dieser
Prozeduren in ARTA ist wie folgt:
Zur Realisierung der Timerverwaltung, deren Semantik im Bild 5.4 geschildert wurde, sollen zwei Rückruf-Funktionen vorgesehen werden, ,,TimerProc”
und ,,settingTimer”. Der Aufruf von ,,TimerProc” bedeutet, dass ein Zeitereignis aufgetreten ist. Aufruf von ,,settingTimer” bedeutet, dass ein Timer ggf.
entweder für ein Datum innerhalb einer Woche oder für ,,einen Tag” gesetzt
werden soll. Diese Prozeduren sind wie folgt aufgebaut:
Public Function TimerProc(Hwnd, uMsg, idEvent, dwTime) As Long
0)Aktuellen Timer abbrechen
Dim lRet As Long
lRet = KillTimer(0&, TimerID)
1)Trigger der Zeitereignisses werden bearbeiten
2)Die Variable mit dem Zeitereignismuster modifizieren
3)Die in der Vergangenheit aufgetretenen Zeitereignisse
bearbeiten
4)"settingTimer 0, 0, 0, 0" aufrufen
End If End Function
Public Function settingTimer(Hwnd, uMsg, idEvent, dwTime)
0)Aktuellen Timer abbrechen
Dim lRet As Long
lRet = KillTimer(0&, TimerID)
1)If Ein Zeitereignis innerhalb einer Woche erwartet
TimerID = _
SetTimer(0&, 0&, DauerbisZeitereignis, AddressOf TimerProc)
Else
TimerID = _
SetTimer(0&, 0&, DauereinesTages, AddressOf settingTimer)
End If
End Function
Diese Prozeduren müssen genau die gezeigte Gestaltung besitzen, damit sie
als Rückruf-Funktion von ,,SetTimer” akzeptiert werden. Für die Eingabeparameter von ,,TimerProc” und ,,settingTimer” werden hier immer ,,0” eingesetzt.
Diese Parameter ermöglichen in ,,Visual Basic” (VB) mehr Funktionalitäten,
z.B. die Verbindung von Timern mit Forms.
86
KAPITEL 6. IMPLEMENTIERUNG
6.7.3
Behandlung vergangener Zeitereignisse
Zeitereignisse, die in der Vergangenheit aufgetreten sind sollen berücksichtigt
und deren Trigger bearbeitet werden, falls deren DeadLines noch nicht um sind.
Durch die Berücksichtigung der Deadlines wird festgestellt, ob Trigger eines
Zeitereignisses gefeuert werden dürfen oder nicht. Jedes mal wenn eine zeitlang
kein Timer gesetzt war, sollen solche Zeitereignisse in der Vergangenheit gesucht
werden. Solche Ereignisse sind zunächst in der Systempause zu suchen, wenn
das Accessprogramm oder der Rechner eine zeitlang abgeschaltet war.
Diese Zeitereignisse können auch nach der Bearbeitung von Triggern, die
durch ein Zeitereignis gefeuert wurden, gefunden werden. Nachdem ein Zeitereignis aufgetreten ist, wird der Timer abgeschaltet und gefeuerte Trigger
werden bearbeitet. Die Deadline darf nicht kürzer als 5 Minuten sein. Diese
Grenze kann höher angesetzt werden, falls die Dauer von Triggerbearbeitung
in einer ARTA-Datenbank sehr groß wird oder falls Trigger eines Zeitereignisses auf jeden Fall/unbedingt bearbeitet werden müssen. Die Bearbeitung
solcher Trigger wird mit Hilfe von Funktion ,,processOldTimeEvents” durchgeführt. Annahme: ,,allTimeEvents” ist die Auflistung vom Typ (der Klasse)
,,USys clsSetOfTimeEvents”, die alle Zeitereignismuster beinhaltet. Durch diese Funktion wird folgender Algorithmus realisiert:
1. Begin der Bearbeitung von ,,processOldTimeEvents”
2. In dieser Funktion wird das erste Element der Auflistung ,,allTimeEvents”
(die Agenda) von Zeitereignismustern untersucht.
Tritt das Zeitereignis in der Zukunft auf, gehe zu (7).
3. Liegt sein Erwartungszeit in der Vergangenheit, so werden seine Trigger
bearbeitet.
4. Ausführung des Befehls
,,Call allTimeEvents.addEvents (allTimeEvents.Item.ModifyEventsStaten)”.
Das erledigt zwei Aufgaben:
(a) Durch ,,allTimeEvents.Item.ModifyEventsStaten” wird das erste Objekt der Auflistung durchsucht und modifiziert. D.h. alle absoluten
Zeitereignismuster in diesem Objekt werden als erledigt eingestuft
und gekennzeichnet und bei jedem periodischen Zeitereignismuster
wird der nächste Termin berechnet. Zusätzlich werden die periodischen Zeitereignismuster mit neuen Terminen zurückgegeben.
(b) Die periodischen Zeitereignismuster mit neuen Terminen werden durch
den Befehl ,,allTimeEvents.addEvents(. . . )” wieder in die Auflistung
aufgenommen.
6.7. BESONDERE ASPEKTE
87
5. Nun wird das modifizierte Objekt aus der Auflistung entfernt:
allTimeEvents.Remove
6. Gehe zu der Zeile (1).
7. Ende der Bearbeitung von ,,processOldTimeEvents”
,,processOldTimeEvents” ist eine rekursive Prozedur und endet mit der Erfüllung
der Bedingung der Zeile (2).
88
KAPITEL 6. IMPLEMENTIERUNG
Kapitel 7
Zusammenfassung und Ausblick
In der vorliegenden Arbeit wurde ARTA als eine Erweiterung des Access-Datenbankmanagementsystems um die Triggerfunktionalität implementiert. In ARTA
werden Formulare als Benutzeroberflächen eingesetzt, um Benutzern die Verwaltung von Triggern und Ereignismustern zu ermöglichen. Ereignisse, die in
ARTA spezifiziert und wahrgenommen werden sind ,,atomar” bzw. primitiv.
Dabei können Ereignisse entweder vom Typ ,,Änderungsereignisse” oder vom
Typ ,,Zeitereignisse” sein. Die Triggersprache in ARTA basiert insoweit auf der
Triggersprache von SQL3, dass sie ,,fast” die gleiche Syntax und Semantik in Bezug auf Änderungsereignisse besitzen. Bezüglich Zeitereignissen sind sie dagegen
völlig unterschiedlich, da in SQL3 im Gegensatz zu ARTA Zeitereignisse nicht
unterstützt werden. Um Zeitereignisse zu realisieren, wurden in ARTA Timer
durch Einsatz geeigneter Funktionen von API-Schnittstellen implementiert. Um
Änderungsereignisse erkennen und deren Trigger bearbeiten zu können, sollen
alle Datenbankänderungen durch SQL-Befehle und unter dem direkten Einsatz
von ARTA vorgenommen werden.
Zeitereigniserkennungsgranularität
Wenn Access eine Transaktion von Datenbankänderungen durchführt und
gleichzeitig die Rückruffunktion des Timers aufgerufen wird (Eintreten eines
Zeitereignisses), muss das Zeitereignis eigentlich als nicht geschehen betrachtet werden. Trigger eines solchen Zeitereignisses können nicht direkt bei Ereigniseintritt bearbeitet werden, da in Access eine Transaktion läuft, die durch
Ausführung einer Prozedur begonnen wurde. Diese beiden Vorgänge können in
Access nicht gleichzeitig bearbeitet werden können. Um dieses Problem zu lösen
habe ich in der vorliegenden Arbeit eine Deadline für Zeitereignisse eingeführt.
Bei der Eingabe der Deadline kann eine beliebige Granularität für das Erkennen
des jeweiligen Zeitereignisses eingeplant werden. Dadurch werden Trigger eines
Zeitereignisses gefeuert, obwohl das Zeitereignis nicht direkt an dem definierten
89
90
KAPITEL 7. ZUSAMMENFASSUNG UND AUSBLICK
Zeitpunkt sonder Später wahrgenommen wird.
Erweiterungs- bzw. Verbesserungsvorschläge
Ohne auf den Source Code von Access und DB Engine zugreifen zu müssen,
lässt sich ARTA in folgenden Bereichen erweitern:
Zusammengesetzte Ereignisse:
ARTA unterstützt nur primitive Ereignisse. Solche Ereignisse werden durch Ereignismuster beschrieben, denen bei der Definition eindeutige Namen zugeordnet werden. Diese Benennung von Ereignismustern kann als eine Voraussetzung
(eine Basis) für eine Erweiterung von ARTA um zusammengesetzte Ereignisse
dienen, indem das Eintreten jedes (interessanten) Ereignisses in einer Ereignishistorie protokolliert wird. Um ein zusammengesetztes Ereignismuster zu erkennen, können die eingetretenen (und protokollierten) Ereignisse aus der Historie
abgelesen und mit dem Ereignismuster verglichen werden. Damit werden interessante Datanbanksituationen beschreibbar, z.B. ,,At Zeitereignis AND On
Änderungsereignis”, ,,Beim vierten Eintreten von E”.
Es stellt sich hier die Frage, ob alle auftretenden Ereignisse protokolliert
werden müssen: Wenn alle Ereignisse protokolliert werden, erhält man möglicherweise eine riesige Datenmenge, von der nur ein relativ kleiner Anteil im
weiteren gebraucht wird. Um diese großen Mengen überflüssiger Daten zu vermeiden wäre die Realisierung eines intelligenten Systems nötig, das interessante
Ereignisse bei der Triggerdefinition herausfiltert. Ein solches System könnte z.B.
bei der Definition von zusammengesetzten Ereignismustern nur ,,die beteiligten
primitiven Ereignisse” als interessante Ereignisse einstufen, die dann in der Folge protokolliert werden.
Relative Zeitereignisse
Die Realisierung von relativen Zeitereignissen ist eine weitere Erweiterungsmöglichkeit. Dadurch werden Zeitereignisse erkannt, die eine bestimmte Zeitdauer vor
oder nach periodischen bzw. absoluten Zeitereignissen eintreten: z.B. ,,der letzte Freitag vor dem 15.10.2002” oder ,,6 Monate nach der Anmeldung eines
Diplomarbeitsthemas”.
Verbindung mit anderen Datenbanken
Durch die Benutzung von Schnittstellen wie ODBC bzw. JDBC und AccessADO, kann Access mit anderen Datenbanksystemen verbunden werden. In ARTA
91
wurde die Anfragesprache SQL eingesetzt, um automatische Datenbankänderungen mit Hilfe von VBA-Befehlen (z.B. database.Execute(SQL)) durchzuführen.
Da SQL in vielen Datenbankmanagementsystemen (Oracle, Sybase, DB2, . . . )
eingesetzt wird, bietet sich eine ARTA-Erweiterung an, um auch in diesen anderen Datenbanken die ARTA-spezifische Triggerfunktionalität anzuwenden. Um
eine Kommunikation zwischen Benutzern und Datenbanken in anderen Systemen zu ermöglichen, wird Access als Benutzteroberfläche benutzt. Dabei sollen
entschieden werden, ob z.B. Informationen von Triggern in ARTA (Access) bleiben oder in der jeweiligen Datenbank eingesetzt werden sollen.
Echtzeit-Datenbanksystem
Zeitereignisse werden in ARTA mit einer Deadline versehen. Die Deadline eines
Zeitereignisses kontrolliert, dass ein Zeitereignis Trigger nur innerhalb eines Zeitintervals feuern darf bzw. kann. Das Zeitinterval ist [t, t+Deadline], wobei ab
dem Zeitpunkt t das Ereignis erwartet wird. Wie lange die Bearbeitung solcher
Trigger dauert, ist dabei nicht relevant. Eine mögliche Verbesserungs wäre, auch
eine Zeitgrenze für das Bearbeitungsende von Triggern vorzusehen, die durch
ein Zeitereignis (oder gar Änderungsereignis) gefeuert werden. Dadurch sollte
ein Zeitereignis bzw. Änderungsereignis innerhalb eines Zeitintervales Trigger
feuern dürfen und die Bearbeitung von solchen Triggern sollte innerhalb einer
Zeitdauer fertig sein.
Entwurf eines besseren Parsers
Hat sich ein Fehler bei der Formulierung eines SQL-Ausdrucks eingeschlichen,
so wird erst bei der Ausführung dieses SQL-Ausdrucks (z.B. durch VBA-Befehl
,,database.Execute(SQL)” oder durch Aktualisierungsabfragen) eine detaillierte Fehlermeldung ausgegeben. Daraus kann erkannt werden, dass in Access ein
interner SQL-Parser installiert ist. Leider ist der Access-Parser weder mit Hilfe
von Access- noch VBA-Befehlen vollständig benutzbar. So kann z.B. der Name
der betroffenen Tabelle im SQL-Ausdruck mit Hilfe von Access- bzw. VBABefehlen nicht gefunden werden.
In ARTA sollten SQL-Ausdrücke bis ins Detail analysiert werden, um damit insbesondere die Transitionstabellen herzustellen (Parser-Problem). In der
Analyse sollten z.B. der Tabellenname, die betroffenen Spaltennamen und der
WHERE-Teil eines SQL-Ausdrucks bestimmt werden. Um eine solche Analyse
zu gewährleisten wurde in ARTA ein Parser realisiert, der nicht jeden möglichen
SQL-Ausdruck analysieren (parsern) kann. Er beschränkt sich dagegen auf die
wesentlichen SQL-Ausdrücke zur Erstellung von Transitionstabellen. Die Realisierung eines Parsers, der SQL-Ausdrücke in vollem Umfang analysieren kann
wäre eine deutliche Verbesserung. Der Parser könnte direkt in der Programmier-
92
KAPITEL 7. ZUSAMMENFASSUNG UND AUSBLICK
sprache VBA realisiert werden. Man könnte auch einen Parser in einer anderen
Programmiersprache (z.B. c++ oder Java) programmieren und ihn dann in einem VBA-Code ausführen lassen.
Literaturverzeichnis
[ISHaRa]
Theo Härder, Erhard Rahm: Datenbanksysteme, Konzepte und
Techniken der Implementierung, ISBN 3-540-65040-7, Springer,
1999.
[ISVos]
Gottfried Vossen: Datenbankmodelle, Datenbanksprachen und Datenbankmanagementsystemen, ISBN 3-486-25339-5, Oldenbourg Wissenschaftsverlag GmbH, 2000.
[ISKeEi]
Alfons Kemper, André Eickler: Datenbanksysteme,
Einführung, R. Oldenbourg Verlag München, Wien, 1999.
[ISVrl]
Prof. Dr. Rainer Manthey: Vorlesungsskript zur Vorlesung ,,Informationssysteme”, Universität Bonn, Wintersemester 1999/2000.
[AKHaWi]
Eric N. Hanson, Jennifer Widom: An overview of production rules in database systems, 121-143, The Knowledge Engineering Review, Vol 8:2 1993 Cambridge University Press.
[AKWiCe]
Jennifer Widom, Stefano Ceri: Introduction to Active Database
Systems, Morgan Kaufmann Publishers, 1996.
[AKPaDi]
Norman W. Paton, Oscar Dı́az: Active Database Systems ACM
Computing Surveys, Volume 31, Number 1, March 1999, 63-103.
[AKPat10]
Krishna Kulkarni, Nelson Mattos, Roberta Cochrane: Active Database Features in SQL3, Chapter 10 in (Norman W. Paton: Active
Rules in Database Systems, ISBN 0-387-98529-8, Springer-Verlag,
Berlin Heidelberg, 1999).
[AKPat12]
Stella Gatziu, Klaus R. Dittrich: SAMOS, Chapter 12 in (Norman
W. Paton: Active Rules in Database Systems, ISBN 0-387-985298, Springer-Verlag, Berlin Heidelberg, 1999).
93
Eine
94
LITERATURVERZEICHNIS
[AKPat21]
Jörgen Hansson, Mikael Berndtssen: Active Real-Time Database Systems, Chapter 21 in (Norman W. Paton: Active Rules in
Database Systems, ISBN 0-387-98529-8, Springer-Verlag, Berlin
Heidelberg, 1999).
[AKDiGa]
Klaus R. Dittrich, Stella Gatziu: Aktive Datenbanksysteme, Konzepte und Mechanismen, ISBN 3-932588-19-3, dpunkt-Verlag,
2000.
[DKCrGH]
Armin B. Cremers, Ulrike Griefahn, Ralf Hinze: Deduktive Datenbanken. Eine Einführung aus der Sicht der logischen Programmierung, ISBN 3-528-04700-3, Vieweg & Sohn Verlagsgesellschaft
mbH, Braunschweig/Wiesbaden, 1994.
[AKVrl]
Prof. Dr. Rainer Manthey: Vorlesungsskript zur Vorlesung ,,Aktive Datenbanken und Ereignisorientierte Programmierung”, Universität Bonn, Wintersemester 2000/2001.
[DKVrl]
Prof. Dr. Rainer Manthey: Vorlesungsskript zur Vorlesung
,,Deduktive Datenbanken”, Universität Bonn, Wintersemester
2000/2001.
[VB6Ko]
Michael Kofler: Visual Basic, Programmiertechniken, Datenbanken, Internet, ISBN 3-8273-1428-3, Addison Wesley Longman Verlag GmbH, 1999.
[VBAHGG] Ken Getz, Mike Gilbert: Visual Basic Language Developers Handbook, chapter 3 & chapter 6 SYBEX, Alameda 2000.
[APIHnd]
Götz Reinecke: Das API Handbuch, Ein Artikel über die
Verwendung des APIs unter Visual Basic, Version 1.02,
http://www.activevb.de, 7/2001.
[APIApp]
Dan Appelman: Dan Appelmans Win32 Puzzle-Buch, Puzzles und
Tutorials für Visual Basic-Profis, ISBN 3-934358-21-7, Galileo
Press GmbH, Bonn, 2000.
[A00AN]
Ralf Albrecht, Natascha Nicol: Access 2000 Programmieren, Professionelle Anwendungsentwicklung mit Access und VBA, ISBN
3-8273-1547-6, Addison-Wesley, 2000.
[A00BK]
Wayne F. Brooks, Lars Klander: Professionelle Access 2000 Programmierung, ISBN 3-8266-0577-2, MITP-Verlag GmbH, Bonn,
1999.
LITERATURVERZEICHNIS
[A97AN]
95
Ralf Albrecht, Natascha Nicol: Microsoft Access 97, Das Handbuch, Das ganze Softwarewissen, ISBN 3-86063-135-7, Microsoft
Press Deutschland, 1998.
[A0SQLBB] Irene Brauer, Jürgen Bär: Access 2000 und MS SQL Server im
Teamwork, ISBN 3-446-21473-9, Carl Hanser Verlag, München
Wien, 2000.
[ASQLMH]
Norbert Michelmann, Rolph Hettwer, Mitarbeit: Hans-Dieter
Schmidt: Datenbankentwicklung und -anpassung mit MS Access
und SQL, ISBN 3-8237-6802-6, Verlag H. Stam GmbH, Köln,
2001.
[dplLein]
Hans-Hermann Leinen: Ein Präprozessor zur Implementierung einer temporalen Erweiterung von SQL, Diplomarbeit an der Universität Bonn, Institut für Informatik III, August 2001.
[dplLoeh]
Torsten Löhr: Eine Erweiterung der aktiven Regelsprache Phoenix
um temporale Ereignisse, Deadlines und Alternativen, Diplomarbeit an der Universität Bonn, Institut für Informatik III, Mai
1997.
[dplModi]
Jürgen Modic: Eine Erweiterung des Triggerkonzeptes von Phoenix um temporale Ereignisse, Diplomarbeit an der Universität
Bonn, Institut für Informatik III, August 2001.
[dplMuen]
Sascha Münch: ARA, Eine Erweiterung des relationalen Datenbanksystems Access um Trigger, Diplomarbeit an der Universität
Bonn, Institut für Informatik III, Oktober 2001.
[AutoHoUl]
John E. Hopcroft, Jeffrey D. Ullmann: Einführung in die Automatentheorie, formale Sprachen und Komplexitätstheorie, ISBN
3-89319-744-3, Addison-Wesley, 1994.
[SQLVrl]
Prof. Dr. Rainer Manthey: Vorlesungsskript zur Vorlesung ,,Relationale Datenbanken”, Universität Bonn, Sommersemester 2000.
[SQLMeSi]
Jim Melton, Alan R. Simon: SQL:1999
Understanding Relational Language Components, Chapter 11,
Morgan Kaufmann Publishers.
[SQLTrKo]
Robert Cochrane, Hamid Pirahesh, Nelson Mattos: Integrating
Triggers and Declarative Constraints in SQL Database Systems,
Site 567-578, IBM Almaden Research Center, SanJose, CA,
www.vldb.org/conf/1996/P567.PDF.
96
[SQLStnd]
LITERATURVERZEICHNIS
American National Standard for Information Technology:
ANSI/ISO/IEC 9075-2-1999, Database Languages -SQLPart2:Foundation (SQL/Foundition), 08.12.1999, 90-92, 387-389,
497-501.
Erklärung gemäß §19,7 DPO
Hiermit erkläre ich, die vorliegende Diplomarbeit selbständig verfasst und keine anderen als die angegebenen Quellen und Hilfsmittel benutzt sowie Zitate
kenntlich gemacht zu haben.
Bonn, den 30. August 2002
97
Herunterladen