Datenbanksystem einer Versicherung Eine Hausarbeit aus dem Praxis-Modul im Bereich der Datenbanksysteme Radek Eckert Im Hollergrund 31 28357 Bremen Email: [email protected] Matrikelnr.: 1563909 1 Inhaltsverzeichnis 1. Einleitung 3 2. Anwendungsfallbeschreibung 3 3. Entity-Relationship-Diagramm einer Versicherung 3.1 Integritätsbedingungen 3.2 Entity-Typen 3.3 Relationships 6 7 8 9 4. Übersetzung in ein Relationales Schema 4.1 Übersetzung der Entity-Typen 4.2 Übersetzung der Relationships 10 10 12 5. Standardanfragen in SQL 12 6. Generierung einer DB-Schicht 6.1 Aufbau des Generators 6.2 Ablauf der Generierung 14 15 17 2 1. Einleitung In dieser Hausarbeit wird der Datenbankentwurf für eine Versicherung zum Thema gemacht. Dabei wird in Punkt 2 zunächst das Anwendungssystem schriftlich beschrieben, um dieses dann in Punkt 3 in einem graphischen Modell in Form eines Entity-Relationship-Diagramms darzustellen. In Punkt 4 wird dann das Modell, also das ER-Diagramm in ein relationales Schema übersetzt. Abschließend werden dann in Punkt 5 einige Standardanfragen in SQL erläutert. In Punkt 6 wird dann ein Thema angesprochen, das ich aufgrund meiner Tätigkeit als Studentische Aushilfe bei einer Versicherung kennen gelernt habe, nämlich die Generierung der Datenbankschicht. Die Quellen für die Ausarbeitung dieser Hausarbeit sind die Inhalte aus der Vorlesung „Datenbanksysteme“ aus dem Wintersemester 03/04 sowie dem Wintersemester 04/05, und mein Wissen über Datenbanken, das ich während meiner oben genannten Tätigkeit erlernt habe. 2. Anwendungsfallbeschreibung In einer Versicherung wird ein System benötigt, das die Informationen des Versicherungsnehmers, kurz VN genannt, in bezug auf seine Abgeschlossenen Versicherungen und anstehenden Zahlungen speichert. Die Zahlungen die dabei gespeichert sind, und in bestimmten Zyklen abgearbeitet werden nennt man Vorgang. Für die Kunden bietet eine Versicherung eine Vielzahl von Leistungen(Versicherungen) an, wobei in dieser Anwendungsfallbeschreibung nur einige der möglichen Leistungen besprochen werden, da es den Umfang dieser Hausarbeit sprengen würde alle Leistungen einer Versicherung zu zeigen. Dabei sind die verschiedenen Leistungen unabhängig voneinander, können jedoch auch zusammen, in einer Art „Paket“ erworben werden. Zu den Leistungen die dargestellt werden gehören: - KFZ-Versicherung(KFZ-V) KFZ-Rechtschutzversicherung(KFZ-RS) Rentenversicherung(RentenV) Lebensversicherung(LV) Rechtschutzversicherung (RS) Haftpflichtversicherung(HpV) Die verschiedenen Versicherungen sind alle auf eine bestimmte Art und Weise auf die Laufzeit bezogen. Die LV und RentenV haben zum Beispiel eine feste Laufzeit, die jedoch gekündigt oder verlängert werden kann. Bei der KFZ-V ist die Laufzeit unbeschränkt, das heißt die Leistung besteht solange, wie das Fahrzeug angemeldet ist, kann jedoch auch zu einem bestimmten Datum innerhalb eines Jahres gekündigt werden. Die restlichen Leistungen (KFZ-RS, RS und HpV) haben auch eine bestimmte Laufzeit, wie bei LV und RV, welche jedoch automatisch verlängert wird wenn man nicht drei Monate vor Ablauf der Laufzeit kündigt. 3 Wie man nun sieht sind die Leistungen bestimmten Zeiträumen zuzuordnen, und deshalb ist es wichtig diese Zeiträume im Anwendungssystem in Bezug auf die Leitung zu speichern. Des weiteren ist es natürlich nötig die Daten des Versicherungsnehmers erfassen zu können. Dazu werden der Name, der Vorname, die Adresse, das Geburtsdatum, die Telefonnummer, die Email-Adresse sowie eine eindeutige VN-Nummer des Kunden im System gespeichert. Manche Versicherungen, wie z.B. RS und HpV, sind davon abhängig ob Familienmitglieder mitversichert werden sollen. Aus diesem Grund sollte das System auch die Möglichkeit bieten Familienmitglieder zu speichern, und es sollte möglich sein in Bezug auf die beiden genannten Leistungen zu erfassen, ob Familienmitglieder mitversichert werden oder nicht. Der Umfang der Daten der Familienmitglieder, ist der Selbe wie der Daten des VN. Jedoch ist es bei den Familienmitgliedern nicht nötig eine eindeutig VN-nummer zu ermitteln. Darüber hinaus sind die KFZ-V und KFZ-RS an ein Fahrzeug gebunden, welches mit folgenden Daten erfasst werden sollte: Typbeschreibung, Kennzeichen, Leistung, Hubraum, Baujahr, Ident-Nr.(Rahmennummer), Marktwert und aktueller KM-Stand. Bei einer KFZ-V sind nicht nur die Daten des Fahrzeugs wichtig, sondern auch andere Daten die zur Berechnung des Beitrags nötig sind. Diese Daten beziehen sich darauf, ob das Fahrzeug auch von Person genutzt wird die unter 23 sind, ob das Fahrzeug nachts in einer Garage steht, wie hoch die maximale KM-Leitung Jährlich ist, bis zu welcher Summe das Fahrzeug bei Schäden versichert werden soll und eine eindeutige KFZ-V# die dieser Leistung zugeordent wird. Auch bei einer KFZ-RS-Versicherung sind weitere Daten nötig. Diese Daten sind wiederrum eine eindeutige KFZ-RS# der man diese Leistung zuordnet. Die Art der Leitung, ob man sich gegen Anklagen andere Versichern will, oder ob man sich auch selber das recht andere anzuklagen mitversichern will. Außerdem gibt es auch hier eine max. Summe, bis zu welcher man Versichert ist, wobei es sich hierbei um die Kosten der Verfahren handelt, und nicht um Sach-/Personenschäden wie bei der KFZ-V. Bei der Lebensversicherung (LV) braucht man die Summe die ausgezahlt werden soll im Todesfall, und natürlich wieder eine eindeutige LV-NR, die dieser Leistung zugeordnet wird. Aus dem Zeitraum wie lange diese Leistung gültig sein soll und der Auszahlungssumme kann man dann die Beiträge berechnen. Die Rentenversicherung ist ähnlich der LV, jedoch wird hier nicht die Summe die im Todesfall ausgezahlt wird gespeichert, sondern die Garantierte monatliche Rente, aus welcher man in Verbindung mit dem Zeitraum wieder die Beiträge berechnen kann. Auch hier wird der Leistung wieder eine eindeutige RV# zugeordnet. Für die normale Rechtsschutzversicherung braucht man die selben Daten wie für die Kraftfahrzeug-RS Versicherung mit einer Zusatzinformation. Nämlich ob Familienmitglieder mitversichert werden sollen, oder nicht. Diese Info braucht man für die KFZ-RS nicht, da diese Leistung auf ein Gegenstand, nämlich das Fahrzeug, bezogen ist. Die Art bezieht sich auch hier darauf ob man sich nur zur Verteidigung versichert, oder aber auch die Möglichkeit mitversichern will andere anzuklagen. Für die Haftpflichtversicherung sollte man auch die Möglichkeit haben Familienmitglieder mit zu versichern. Außerdem sollte man auch hier wieder eine obere Grenze festlegen, bis zu welcher Summe der VN versichert wird, und auch die Art der HpV sollte hier festgelegt werden. Da heißt ob man die Haftpflicht nur auf die eigenen vier Wände begrenzt, oder ob man generell überall versichert sein will. Auch bei dieser Leistung wird wieder eine eindeutige HpV# benötigt. 4 Der Preis, bzw. die Zahlung der Leistungen sollte dabei nicht an die einzelnen Leistungen geknüpft sein, da man Mitarbeiter mit besonderen Rabatten berechnet, oder Premium-Kunden auch Ermäßigungen zu gesprochen bekommen. Deshalb sollten die Zahlungen an die Vorgänge geknüpft sein, die in bestimmten Zyklen abgearbeitet werden. Auch hierzu wird eine eindeutige Zahlungs# benötig. Außerdem sollte man die Auswahl haben, ob monatlich, viertel jährlich oder jährlich die Beiträge zahlt. Diese Auswahl wird in der Art der Zahlung gespeichert. Darüber hinaus gehört zur Zahlung noch der Betrag der Zahlung und die Zahlart(Überweisung, einzugsermächtigung,…). Wie man sieht werden zu Daten die gespeichert werden sollen eigene eindeutige Nr. erzeugt, um die Handhabung dieser Daten zu vereinfachen. Das ist zwar nicht unbedingt nötig, jedoch von hohem Nutzen wenn eine Kunde zum Beispiel anruft und etwas ändern will. Dann braucht man nicht viele Verschiedenen Daten einzugeben, oder lange zu suchen. Des weiteren ist diese Tatsache auch für die elektronischen Anwendungen von hohem Nutzen, da diese Nummern eindeutig sind. Man braucht also nicht mehrere Spalten oder Attribute um einen Kunden oder eine Leistung eindeutig zu identifizieren, sondern nimmt einfach die Eindeutige Nummer, die dann auch gleichzeitig der Primary Key ist. 5 3. Entity-Relationship-Diagramm einer Versicherung (Ausschnitt) 6 3.1 Integritätsbedingungen Um in einem Datenbanksystem nur Daten zu Speichern die bzgl. des Anwendungssystems semantisch korrekt sind, sollte man Integritätsbedingungen festlegen. In dem Konzept der Versicherungs-Datenbank sind bereits zwei Arten von Integritätsbedingungen enthalten. Die erste Art sind dir Primärschlüssel jeder Tabelle, die immer gefüllt sein sollten um die einzelnen Datensätze eindeutig unterscheiden zu können. Die zweite sind die Kardinalitäten die zwischen Datensätzen bestehen. Nachfolgend werden Beispiele solcher und andere Zusicherungen aus dem Konzept Dargestellt, die erfüllt sein sollten um die Konsistenz der Daten zu sichern. 1. Der Name, Vorname und das Geburtsdatum aus der Tabelle Person, müssen immer mit Werten gefüllt sein (Primärschlüssel): forAll p: PERSON p.Name is not Null and p.Vorname is not Null p.Geburtsdatum is not Null 2. Die VN-nummer(VN#) vom Entity-Typ VN(Versicherungsnummer) muss eindeutig sein: forAll v1, v2: VN v1.VN# = v2.VN# v1 = v2 3. Des weiteren sollten VN geschäftsfähig, also mindestens 18 Jahre alt sein. Die Funktion today() wird dazu benötigt und liefert das heutige Datum zurück. forAll v: VN (today() – v.Geburtsdatum) >= 18 Jahre 4. Versicherungen können nur für Personen und Familienmitglieder abgeschlossen werden, die bereits geboren sind: forAll v: VERSICHERUNG, p: Person, f: Familienmitglied p v.abgeschlossenFür p.Geburtsdatum >= date(v.BeginDatumZeit) & f v.abgeschlossenFür f.Geburtsdatum >= date(v.BeginDatumZeit) 5. Falls sich die Versicherung auf einen bestimmten Zeitraum beschränkt, welches meistens der Fall ist, muss das Datum des Beginns vor dem Datum des Endes liegen: forAll v: VERSICHERUNG v.BeginDatumZeit is not Null and v.EndeDatumZeit is not Null v.BeginDatumZeit <= v.EndeDatumZeit 7 6. Kennzeichen von versicherten Fahreugen müssen eindeutig sein: forAll a1, a2 : KFZ k1.Kennzeichen = k2.Kennzeichen k1 = k2 7. Jedes Familienmitglied gehört zu mindestens einem VN: forAll f: FAMILIENMITGLIED f.vn# is not Null 8. Versicherungen die sich auf ein KFZ beziehen (KFZ-RS, KFZ-V), müssen das Kennzeichen des Fahrzeugs enthalten: forAll av: KFZ-V av.Kennzeichen is not Null In diesem Konzept gibt es noch mehr Daten deren Konsistenz gesichert werden sollte. Als Beispiele sollte diese Integritätsbedingungen jedoch reichen, da die fehlenden Integritätsbedingungen der 2. und 6. Bedingung sehr ähneln. 3.2 Entity-Typen Entity-Typen sind Objekte aus der Anwendungsfallbeschreibung, die in dem ER-Diagramm in einem Rechteck dargestellt wurden. Die Attribute dieser Entities sind als abgerundete Rechtecke dargestellt und jeweils über eine Kante mit dem Entity-Typ verbunden. Des weiteren sollte erwähnt werden das die Attribute als verschiedene Datentypen (int, string, boolean,..) deklariert sein können. Ich hab jedoch aus Platzgründen darauf verzichtet. Vereinfachend kann man sagen das die Entity-Typen später die Tabellen der Datenbank darstellen, und die dazugehörigen Attribute sind die darin enthaltenen Spalten. Nachfolgend werden alle im ER-Diagramm verwendeten Entity-Typen textuell dargestellt, wobei bei der Erstellung des Diagramm das Verständnis im Vordergrund stand und nicht Vollständigkeit der Entity-Typen. Das heißt in einem echten Modell aus einer Versicherung würden die Entity-Typen wahrscheinlich eine größere Anzahl an Attributen besitzen. a) PERSON (Name, Vorname, Geburtsdatum, Adresse, Telefon, Email) b) VN (VN#, Name, Vorname, Geburtsdatum, Adresse, Telefon, Email) c) FAMILIENMITGLIED (Name, Vorname, Geburtsdatum, Adresse, VN#) d) VORGANG (Vorgangs#) e) VERSICHERUNG (BeginDatumZeit, EndeDatumZeit, Beschreibung) 8 f) KFZ-V (KFZ-V#, max KM-Leistung, max Vers.-Summe, unter23 J/N, Garage J/N) g) KFZ-RS (KFZ-RS#, Art, max Vers.-Summe) h) L-V (LV#, Auszahlugsbetrag) i) Renten-V (Renten#, garantierte montl. Rente) j) RS-V (RS#, Art, max Vers.-Summe, Familie J/N) k) HpV (HpV#, Art, max Vers.-Summe, Familie(J/N) ) l) KFZ (Kennzeichen, Leistung, Hubraum, Wert, aktueller KM-Stand, Baujahr, Typenbezeichnung, Ident-Nr.) m) ZAHLUNG (Zahlungs#, Zyklus, Betrag, Zahlart, Bezahlt(J/N) ) Die unterstrichenen Attribute eines Entity-Typs ergeben den Primärschlüssel. Dieser Schlüssel dient dazu Entities eindeutig identifizieren zu können, als Voraussetzung gilt das es keine Entities mit gleichem Primärschlüssel gibt. Diese Tatsachen sollte man in den Integritätsbedingungen abfangen. 3.3 Relationships Relationships sind Beziehungen zwischen Objekten bzw. Entities aus dem ER-Diagramm. Sie werden graphisch durch Rauten dargestellt und verbinden die jeweiligen Objekte über Kanten. Über Kardinalitäten kann man festlegen wie oft eine Entity an einer Beziehung beteiligt sein kann. Als Beispiel kann man die Beziehung aus f) nehmen die in dem ER-Diagramm mit der Kardinalität [1,*] auf der Person-Seite und [0,*] auf der Seite festgelegt wurde. Dieses wurde so festgelegt, damit ein Familienmitglied mindestens zu einer Person gehörten muss. Eine Person kann also keine bis beliebig viele Familienmitglieder haben. Auf der anderen Seite muss ein Familienmitglied mindestens zu einer Person bzw. VN zugeordnet sein. Nachfolgen werden alle Beziehungen aus dem Modell textuell dargestellt. a) durchgeführtFür (Vorgang, VN) b) abgeschlossenFür (Versicherung, Person) c) abgeschlossenFür (Versicherung, Familienmitglied) d) teilVon (Versicherung, Vorgang) e) gehörtZu (Zahlung, Vorgang) f) gehörtZu (Familienmitglied, Person) 9 g) gehörtZu (KFZ, KFZ-V.) h) gehörtZu (KFZ, KFZ-RS) i) ist (RSV, Versicherung) j) ist (LV, Versicherung) k) ist (Renten-V., Versicherung) l) ist (KFZ-V., Versicherung) m) ist (KFZ-RS, Versicherung) n) ist (HpV, Versicherung) 4. Übersetzung in Relationales Schema Die zuvor gezeigten Entity-Typen und Beziehungen werden hier in ein Relationales Datenbank Schema übersetzt. Dazu wird die Gliederung des vorherigen Punktes übernommen. 4.1 Übersetzung der Entity-Typen a) PERSON (Name, Vorname, Geburtsdatum, Adresse, Telefon, Email) Aus dem Entity-Typ PERSON wird das Relationenschema PERSON, das neben dem Namen auch Attribute und Schlüssel übernimmt. b) VN (VN#, Name, Vorname, Geburtsdatum, Adresse, Telefon, Email) VN (Versicherungsnehmer) ist über eine ist-Beziehung mit PERSON verknüpft. Wie der Name der Beziehung schon sagt ist VN eine Person. Deswegen wird das Rel.-Schema VN um die Attribute von PERSON ergänzt. Der Primärschlüssel ist dabei die eindeutige generierte VN#. c) FAMILIENMITGLIED (Name, Vorname, Geburtsdatum, Adresse, VN#) FAMILIENMITGLIED übernimmt die Attribute aus dem gleichnamigen Entity-Typ. VN# ist der Fremdschlüssel der speichert zu welchem VN das Familienmitgl. gehört. 10 d) Der Entity-Typ VORGANG wird nicht in ein relationales Schema übersetzt, da er immer zu einer VERSICHERUNG gehört. Deshalb wird VORGANG mit seinem Attribut in das relationale Schema VERSICHERUNG integriert. e) VERSICHERUNG (Vorgangs#, BeginDatumZeit, EndeDatumZeit, Beschreibung) Das Relationenschema VERSICHERUNG wird aus den Entity-Typen VERSICHERUNG und VORGANG gebildet, die über die Beziehung teilVon verknüpft sind. Da zu jedem Vorgang genau eine Versicherung existiert, kann man für dieses Schema den PK (Primary Key) von VORGANG übernehmen. Die Attribute setzen sich aus den Attributen beider Entity-Typen zusammen. f-l) KFZ-V (KFZ-V#, max KM-Leistung, max Vers.-Summe, unter23 J/N, Garage J/N, Vorgangs#, Kennzeichen) KFZ-RS (KFZ-RS#, Art, max Vers.-Summe, Vorgangs#, Kennzeichen) L-V (LV#, Auszahlugsbetrag, Vorgangs#) Renten-V (Renten#, garantierte montl. Rente, Vorgangs#) RS-V (RS#, Art, max Vers.-Summe, Familie J/N, Vorgangs#) HpV (HpV#, Art, max Vers.-Summe, Familie(J/N), Vorgangs#) Die Entity-Typen aus den Punkten f) bis l), die über eine ist-Beziehungen mit VERSICHERUNGEN verknüpft sind, behalten die Attribute aus ihrem Entity-Typ. Darüber hinaus erhalten sie jeweils die Vorgangs# der Versicherung zu der sie gehören, also einen Fremdschlüssel. Außerdem erhalten die beiden Versicherungen die sich auf ein KFZ beziehen das Kennzeichen des Fahrzeugs als Fremdschlüssel. l) KFZ (Kennzeichen, Leistung, Hubraum, Wert, aktueller KM-Stand, Baujahr, Typenbezeichnung, Ident-Nr.) Das Relationenschema KFZ übernimmt die Attribute aus dem gleichnamigen Entity-Typ. m) ZAHLUNG (Zahlungs#, Zyklus, Betrag, Zahlart, Bezahlt(J/N), Vorgangs#) Das Relationenschema ZAHLUNG übernimmt die Attribute des gleichnamigen EntityTyps. Darüber hinaus wird die Vorgangs# als Fremdschlüssel hinzugefügt, da jede Zahlung zu einem Vorgang gehört, wie man den Kardinalitäten aus dem ER-Diagramm Entnehmen kann. 11 4.2 Übersetzung der Relationships Bei der Übersetzung der Beziehungen in ein relationales Schema, geht es darum die Beziehung zwischen zwei Einträgen in der Datenbank eindeutig bestimmen zu können. Dazu bietet es sich an die Primärschlüssel der Relationenschema, die in Beziehung zueinander stehen, zur Identifikation zu verwenden. Nachfolgend stelle ich die relationalen Relationships mit den Attributen zur Identifikation der Einträge dar. Da ist-Beziehungen Vererbungsbeziehungen sind, die zur Spezialisierung von Entities gebraucht werden, werden sie nicht übersetzt. Auch die „teilVon“-Beziehung aus Punkt d) wird nicht übersetzt, da es für den EntityTyp VORGANG kein relationales Schema gibt. Einige Name der relationalen Beziehungen mussten angepasst werden, damit man Sie Abfragen kann, da man keine zwei Beziehungen in einer relationalen Datenbank erzeugen kann mit dem gleichen Namen. a) durchgeführtFür (Vorgangs#, VN#) b) abgeschlossenFürP (Vorgangs#, Name, Vorname, Geburtsdatum) c) abgeschlossenFürFM (Vorgangs#, Name, Vorname, Geburtsdatum) e) ZgehörtZu (Zahlungs#, Vorgangs#) f) FMgehörtZu (Name, Vorname, Geburtsdatum, Name, Vorname, Geburtsdatum) g) gehörtZuV (Kennzeichen, KFZ-V#) h) gehörtZuRS (Kennzeichen, KFZ-RS#) 5. Standardanfragen in SQL In diesem Abschnitt werde ich ein paar Standardanfragen an eine Datenbank als Beispiele für Anfragen mit der Datenbanksprache SQL zeigen, welche die zur Zeit meist verbreitetste relationale Sprache für Anfragen an eine Datenbank ist. Standardanfragen an die Datenbank sind Anfragen über bereits bestehende Datensätze und werden in SQL über der Befehl “select“ ausgeführt. Dieser Befehl besteht aus einem sogenannten SWF-Block. SWF steht für Select, From, Where. Select ist der Befehl zur Auswahl von Einträgen in der Datendank, From ist das Schlüsselwort nachdem der Name der Tabelle stehen muss und Where ist die Klausel nach der die Einschränkungen stehen, nach denen man die Einträge haben möchte (Selektionsbedingungen). Als erstes Beispiel zeige ich nun ein SQL-anfage an das relationale Schema VN, dabei will ich alle Familienmitglieder zu einem bestimmten Versicherungsnehmer wissen. 12 select * from FAMILIENMITGLIED where VN# = vn#desVN Bei dieser Anfrage würde man nun alle Familienmitglieder des Versicherungsnehmers bekommen, dessen VN# in der Variable “vn#desVN“ steht. Der Stern hinter dem select bedeutet das man alle Spalten bzw. Attribute in das Ergebnis bekommen möchte. Man könnte auch explizit nur die Spalten da hin schreiben, die einen interessieren. select KFZ.Kennzeichen, max KM-Leistung, max Vers.-Summe, unter23 J/N, aktueller KM-Stand from KFZ, KFZ-V where KFZ.Kennzeichen = KFZ-V.Kennzeichen and KFZ-V# = akt_Fall In der zweiten Anfrage werden Spalten aus den zwei Relationen KFZ und KFZ-V verlangt. Bei solch einer Anfrage muss man die Attribute mit gleicher Bezeichnung, in diesem Fall Kennzeichen, zur eindeutigen Identifizierung mit dem Relationsnamen und einem Punkt vor der Attributbezeichnung kennzeichnen. Die Ergebnismenge dieser Anfrage ist genau eins, und besteht aus jeweils einem Eintrag der beiden Relationen KFZ und KFZ-V. Dabei wird nun der Eintrag der Tabelle KFZ-V gefunden, bei dem die KFZ-V# mit der Nummer aus der Variable akt_Fall übereinstimmt. Dazu wird dann das dazugehörige Fahrzeug über da Kennzeichen gefunden, vorausgesetzt das diese Einträge wirklich existieren. Eine solche Anfrage wäre für einen Sachbearbeiter einer Fachabteilung notwendig, zum Beispiel bei der Bearbeitung eines Unfalls mit dem versicherten Fahrzeug. Bei der nächsten Abfrage handelt es sich um eine Verschachtelte Abfrage, bei der alle Zahlungen zu einem Versicherungsnehmer berechnet werden sollen. Als erste braucht man alle Vorgänge(Vorgangs#) zu einem VN(VN#), dabei nehme ich an das der VN bekannt ist. Dazu werden nun zu erst die Vorgangs#(n) zu einem VN geholt, dessen # in der Variablen bearb# steht. select Vorgangs# from durchgeführtFür where VN# = bearb# Wenn die Vorgänge bekannt sind, braucht man die Zahlungen(Zahlugs#) zu den Vorgängen. Dazu wird die obere Abfrage nun in eine andere Abfrage integriert, um über die Vorgangs#(n) an die Zahlungs#(n) zu gelangen. select Zahlungs# from ZgehörtZu where Vorgangs# in (select Vorgangs# from durchgeführtFür where VN# = bearb#) Bei dieser verschachtelten Abfrage wird zu erst die innere Abfrage ausgewertet, also die Vorgangs#(n) für einen VN geholt. Anschließend wird in der Relation ZgehörtZu nach den Einträgen gesucht, welche die gefundenen Vorgangs#(n) enthalten. Im Gesamtergebnis dieser Abfrage werden dann nur die Zahlungs#(n) zu einem VN angezeigt. 13 Anhand dieser Zahlungs#(n) könnte man nun eine weitere Abfrage integrieren, welche den zu zahlenden Gesamtbetrag aus den einzelnen Einträge der Relation ZAHLUNG berechnet. Da eine solche Rechnungsart in der Versicherungsbranche unüblich ist, weise ich hier nur darauf hin das so etwas möglich ist. In diesem Fall würde man nun für jede gefundene Zahlungs# eine Abfrage auf die Relation ZAHLUNG machen, um den Zyklus und den Betrag der Zahlung zu holen und dann mit diesen Daten die einzelnen Rechnungen zu schreiben. 6. Generierung einer DB-Schicht In diesem Abschnitt möchte ich Ihnen ein Modell vorstellen das es der Versicherung bei der ich arbeite ermöglicht die gesamte Datenbank-Schicht automatisch zu generieren. Dabei wird hier zuerst der Sinn und Zweck eines solchen Generators erläutert, um dann im nächsten Punkt den Aufbau des Generators und die einzelnen Komponenten vorzustellen. Wie man sich vorstellen kann, gibt es bei großen Versicherungen mit über 2000 Mitarbeitern einen riesigen Datenbestand der zu Verwalten ist. Dabei handelt es sich nicht nur um Kundendaten, sondern auch um Daten von Mitarbeitern, Technische Daten usw. Diese Daten werden auf DB2 Datenbanken auf dem HOST gespeichert. Dazu gibt es eine Unmenge von Tabellen die es zu verwalten gilt. Da diese Tabellen auf dem HOST sind, und man Kompatibilität zu den Alten Anwendungen waren will, werden die DB-Handler in COBOL geschrieben. Wie man sich vorstellen kann, müssen diese DB-Handler in einer bestimmten Form und nach bestimmten Richtlinien geschrieben sein. Diese Richtlinien besagen auch das man eine Mengen von Sicherheitsabfragen und spezieller Scripte aufrufen muss. Durch die Möglichkeit der automatischen Generierung von DB-Handlern kann man sich all diese „Standard Tipparbeit“ sparen. Der erste wichtige Grund um solche Programme automatisch zu generieren ist also das man sich viel Zeit und Arbeit spart. Der zweite Grund ist das man dadurch die Fehleranzahl auf ein Minimum reduzieren kann. Da man den generierten Code schon ausgiebig getestet hat, wird dieser unter normalen Umständen keine Fehler produzieren. Falls es wieder erwarten doch zu Fehler beim generieren kommen sollte, werden diese in einer Protokoll-Datei festgehalten. Falls in dieser Datei nun keine Fehler stehen, also es beim generieren zu keinen Problemen gekommen ist, kann man davon ausgehen das der Code fehlerfrei ist. Ist dieses nun nicht der Fall, kann man die Fehlersuche auf den Individuell veränderten Anteil des DB-Handlers beschränken. Aber dazu später mehr. Man kann also auch bei der Fehlersuche viel Zeit sparen. Die Hauptgründe sich für einen solchen Generator zu entscheiden sind also das man viel Zeit sparen kann beim Tippen und bei der Fehlersuche. Und da in der Wirtschaft Zeit bekanntlich auch gleich Geld ist, ist der Einsatz einer solchen Technik nur all zu logisch. 14 6.1 Aufbau des Generators In diesem Punkt soll nun der Aufbau und die Funktionsweise des DBH-Generators erläutert werden. Dazu werden in der Abbildung die einzelnen Komponenten und Ihre Abhängigkeiten dargestellt, um sie dann später genauer vorzustellen. Wie man sehen kann wurde zur der Realisierung des Generators ein Scritp-Interpreter und ein Makro-Processor entwickelt. Diese beiden Programme beziehen Ihre Informationen aus den COBOL-Bausteinen, dem Ablauf-Script, den DBH-Vorlagen und dem DB2-Katalog, und generieren daraus den DBHandler(COBOL) und eine Protokoll-Datei. COBOLBausteine Makro Processor AblaufScript Script Interpreter DBH Vorlagen DB2 Katalog Protokoll DB-Handler COBOL-Bausteine: Diese sogenannten Bausteine (auch Templates genannt) beinhalten den eigentlichen Code aus dem später der DB-Handler entsteht. Wobei diese Bausteine in einer Script-Sprache namens „IREX“ geschrieben sind. Dieses IREX ist REXX sehr ähnlich, und wurde bei meinem Arbeitgeber entwickelt. Der Script-Interpreter, zu dem wir später noch kommen, interpretiert diese Script-Sprache. Man könnte diesen Code auch in einen einzigen Baustein implementieren, welches jedoch aus Gründen der Übersichtlichkeit nicht von Vorteile wäre. Um eine gewisse Übersicht zu waren, wurde der gesamte Code in viel kleinere Bausteine aufgeteilt. Des weiteren ist der Interpreter so geschrieben, das er Fehler zur Laufzeit des Generierens so protokolliert, das man sehen kann in welchem der Bausteine die Probleme zu finden sind. Diese Baustein gibt es nur einmal für alle zu generieren den DB-Handler, die Ausgabe dieser Bausteine ist der COBOL-Code der in eine Datei geschrieben wird. 15 Ablauf-Script: Das Ablauf-Script ist eigentlich auch ein Baustein der in IREX geschrieben ist, der so etwas wie das Hauptprogramm des Generators ist. Diese „Hauptprogramm“ bestimmt in welcher Reihenfolge die COBOL-Bausteine ausgeführt werden. Außerdem sagt es dem Interpreter welche Vorlage gelesen werden muss und um welche physische Tabelle es sich handelt. Diese und andere Infos braucht der Interpreter um spezielle Befehl, die zum generieren von Code implementiert wurden, auszuführen. Auch dieses Ablauf-Script gibt es nur einmal für alle DB-Handler. Wobei beim Aufruf des Scripts der physische Name der Tabelle, und der Name des zu generierenden DB-Handlers übergeben werden muss. DBH-Vorlagen: Hierbei handelt es sich um Dateien in denen Variablen gespeichert werden die zum generieren des DB-Handlers nötig sind. Die erste Art Variablen beinhalten Text wie zum Beispiel den Namen des Verantwortlichen dieses DB-Handlers oder die Name der Schnittstellen(COBOLCopystrecken). Die Zweite Art von Variablen dieser Vorlagen beeinflusst das Verhalten des Generators, z.B. ob Standard SQL-Zugriffe, die in unserem Fall INSERT, SELECT, UPDATE und DELETE sind, generiert werden sollen oder nicht. Darüber hinaus gibt es noch Variablen die individuellen Code speichern, wenn nötig, und ihn dann an bestimmten Stellen in den DB-Handler einbauen. Individueller Code sind in der Regel ein oder mehrere spezielle SQL-Abfagen, die man nicht Standardisieren kann. Diese Vorlagen kann man eigentlich mit sogenannten Haeder-Files vergleichen, wobei hier die Variablen bestimmte Namen haben, die beibehalten werden müssen, damit der Generator die Variablen erkennt. Jeder DB-Handler benötig eine Vorlage, somit gibt es eine Vielzahl von Vorlagen die einfach unter dem Namen der Tabelle gespeichert werden. DB2-Katalog: Mit diesem DB2-Katalog sind die eigentlichen zu Verwaltenden Tabellen gemeint. Wobei der Generator in diesem Fall nur die Spalten- bzw. Attributnamen der Tabelle aus DB2 liest. Diese Informationen werden zum generieren von SQL-Abfragen gebraucht. Dazu stellt DB2 Methoden zur Verfügung, mit denen man das Layout von Tabellen untersuchen kann. Makro-Processor: Der Makro-Processor ist dazu da, um Makro-Befehle aus den Bausteinen Aufzulösen. Makro-Befehle sind in diesem Fall spezielle Befehle, die nicht mit normalen Sprachbefehlen zu Vergleichen sind. Ein Beispiel dafür ist ein Befehl der die Spaltennamen aus DB2 holt und dann in der Ausgabe auflöst. Makro-Befehle werden mit „+“ eingeleitet. Man kann diese Makro-Befehl auch mit einem Methodenaufruf vergleichen. Den Makro-Processor gibt es nur einmal, wobei dieses Programm nicht nur für den Generator benutzt wird, sondern auch in Anwendungsprogrammen zum auflösen von Makros. 16 Script-Interpreter: Der Script-Interpreter ist dazu da, um IREX zu kompilieren und auszuführen. Diese ScriptSprache ist 1996 entwickelt worden, um eine solche Technik, die Code generiert auf dem HOST zu ermöglichen. Diese Sprache ist ziemlich einfach gehalten und REXX sehr ähnlich. Sie beinhaltet meines Erachtens nach nur die einfachsten Sprachkonstrukte wie Zuweisungen, Mathematische/Boolsche Operatoren und Schleifenkonstrukte. Alle anderen benötigten Sprachkonstrukte wie zum Beispiel das Einlesen einer Datei(COBOL-Baustein), wurden mit Makro-Befehlen realisiert. Protokoll: Das Protokoll ist eine Datei, in die während des Generierungs-Vorgangs geschrieben. In dieser Datei wird die Generierung, wie der Name schon verrät, protokolliert. Dazu gehörten solche Aussagen wie zum Beispiel der Begin des Vorgangs mit Datum und Uhrzeit. Gegebenfalls Fehler die während des Vorgangs auftreten und abschließend der Abschluss Des Vorgangs wieder rum mit Datum und Uhrzeit. DB-Handler: Der DB-Handler ist das Ergebnis des Generierungs-Vorgangs, ein vollständig generiertes und voraussichtlich lauffähiges COBOL Programm. Das generierte Programm muss nun von einem COBOL-Compiler kompiliert werden. Falls dabei Fehler gefunden werden sollten, und im Protokoll keine Fehler protokolliert wurden, kann man davon ausgehen das der Fehler aus dem selbst programmierten Code stammt. Dieses kann man dann mit den Fehlermeldungen des COBOL-Compilers überprüfen. Falls wieder erwarten der Fehler nicht in diesen Codeabschnitten ist, sollte man die Mitarbeiter der Technik über diesen speziellen Fehler informieren. 6.2 Ablauf der Generierung In diesem Punkt wird der Ablauf des gesamten Generierungs-Vorgangs von A bis Z erläutert. Dabei werden stichpunktartig alle nötigen Eingaben am Beispiel einer neuen Anwendung dargestellt. Man stelle sich vor das man für eine neue Anwendung eine neue DatenbankTabelle braucht, wie es bei großen Versicherungen öfter der Fall ist. Dieses ist zum Beispiel der Fall gewesen als die neue Riester-Rente beschlossen wurde. Dazu brauchte man selbstverständlich eine oder mehrere Tabellen die alle Daten speichert und eine Anwendung die alle nötigen Berechnungen vornimmt. Darüber hinaus braucht man auch ein Programm das die Kommunikation zwischen der Anwendung und der Datenbank abwickelt. Ein solches Programm nennt man bei meinem Arbeitgeber DB-Handler (Datenbank-Handler). Nun kommt unser DBH-Generator ins Spiel, welcher entwickelt wurde um die Arbeit der Anwendungsprogrammierer zu erleichtern. Um einen solchen DB-Handler zu generieren muss man zuerst einige Schritte durchführen. 17 Als erstes sollte man sich mit den dafür Verantwortlich über die Name der zu erstellenden Module, Schnittstellen und Tabelle(n) einigen. Danach sollte man die nötige(n) Tabelle(n) in DB2 anlegen. Wenn die Tabellen angelegt sind, sollte man sich Gedanken machen welche speziellen SQL-Zugriffe, die nicht über Primary Key laufen man braucht. Wie schon erwähnt kann man über einen Schalter alle Standard-Zugriffe (INSERT, SELECT, UPDATE und DELETE) die über den PK abgefragt werden generierten. Darüber hinaus braucht man sicherlich auch andere Abfragen. Diese sollte man vorher festlegen. Nachdem man sich nun über die SQL-Zugriffe Gedanken gemacht hat, kann man die Vorlage schreiben. Dazu müssen alle benötigten Variablen erfasst werden. Zum generieren der speziellen Zugriffe muss eine Variable erfasst werden in der die Anzahl n der speziellen Zugriffe speichert werden. Dann sollte der SQL-Code der Zugriffe in Variablen SQL1SQLn gespeichert werden um danach die Art der Zugriffe in den Variablen SQLART1SQLARTn zu definieren. Die möglichen Arten sind z.B. SELECT, UPDATE, DELETE, CURSOR usw. Diese Arten sind wichtig für den Vorgang der Generierung. Zum besseren Verständnis wird hier dieser Vorgang kurz an einem Beispiel dargestellt, das alle Zahlungen über 1000 Euro Abfragen soll. SQL_ANZ = 1 SQL1 =“ SELECT ALL FROM ZAHLUNGEN WHERE Betrag >= 1000“ SQLART1 = „SELECT“ Diese spezielle Anfrage wird nun im DBH erzeugt und in eine Methode gesteckt, deren Namen auch nach speziellen Konventionen erzeugt werden, damit die Anwendungsprogrammierer sie ohne Probleme über einen „CALL“ aufrufen können. Wenn die Vorlage vollständig erfasst ist, muss noch die Zugriffs-Copystrecke (COBOLSchnittstelle für DB2) erstellt werden. Nachdem auch dies erledigt ist, kann man den Generator starten indem man den Interpreter aufruft mit den Parametern: Scriptname(Ablaufscript), DB-Handler Name und Tabellenname. Für die Tabelle ZAHLUNGEN würde ein Aufruf so aussehen: IREX DBHGEN(Z$DBGEN) DBH-ZAHLUNGEN ZAHLUNGEN Nun wird der DBH DBH-ZAHLUNGEN für die Tabelle ZAHLUNGEN automatisch erstellt und mit sehr hoher Wahrscheinlichkeit auch sofort Fehlerfrei für die Anwendungsprogrammierer zur Verfügung stehen. Man könnte diesen Vorgang nun genau so für die anderen Tabellen des Modells machen, um dann die Anwendungsprogramme für ein solches Modell zu programmieren. Ich hoffe das ich unseren sogenannten „DBH-Generator“ verständlich dargestellt habe und ich mich nicht zu weit vom Thema entfernt haben. 18