Es gibt viele Gründe, Strukturen in der Datenbank aufzuräumen und reorganisieren. Sei es in gewachsenen Applikationen, sei es bei der Modernisierung oder dem Zugriff von weiteren Front-Ends auf die gleichen Datenbank Sourcen. Selbst wenn eine komplett neue Architektur aus einer Modellierung übernommen werden soll, wird recht schnell klar, dass die Datenbank-Objekte in der richtigen Reihenfolge angelegt werden müssen. Das ist zunächst offensichtlich und jedem klar. Sequences vor Tabellen, Tabellen vor Views vor PL/SQL-Funktionen und Prozeduren …
Schwieriger zu bestimmen wird es, wenn gleiche Objekt-Typen untereinander abhängig sind, z.B. wenn Typen auf Typen aufsetzen. Hier die richtige Reihenfolge zu bestimmen ist nicht immer trivial, gerade dann, wenn die Aufgabe darin besteht, in einem skript-gesteuerten Ansatz eine beliebige Vielzahl von TYPE Deklarationen zu erstellen.
Eine gute Möglichkeit bietet hier die Möglichkeit, in der Oracle Datenbank „incomplete Types“ zu erstellen:
Oracle TYPE Syntax
Durch die reine Angabe des Typ-Namen bei dem CREATE-Statement kann dieser Typ zunächst in weiteren Statements genutzt werden und die Implementierung und genaue Spezifikation kann in einem weiteren Verlauf erfolgen. Mit dieser Forward-Deklaration ist eine Ermittlung der Reihenfolge nicht mehr relevant und es können zuerst alle Typen incomplete erstellt werden, bevor die eigentliche Implementierung erfolgt. Für einzelne Skripte kann alternativ auch im „Prefix“ des Skripts sichergestellt werden, dass alle benutzten Typen in einer Forward-Deklaration zunächst angelegt werden.
In größeren Modernisierungsprojekten liegen nach einer Refakturierung die Metadaten häufig in eigenen Tabellen-Strukturen vor. Aus diesen lassen sich dann sehr leicht über Velocity/Texen die passenden Templates für die Generierung der SQL-Skripte erstellen. Bei der Forward-Deklaration der Typen kann dann eine Metadaten-Tabelle und das passende Velocity-Template so aussehen:
SORT | Object_Name | Object_type | object_value |
1 | beispiel_ot | OT | |
2 | name_attribut1 | R | tabelle1.spalte2 |
3 | name_attribut3 | N | varchar2(100) |
4 | name_attribut4 | N | number(12,2) |
5 | name_attribut5 | T | anderer_ot |
6 | name_attribut6 | C | base_type |
Dabei kann innerhalb des Object_types unterschieden werden:
- R: verweist auf den Spalten-Typ einer existenten Tabelle
- N: normaler, simple Oracle Datentyp, z.B. Number, Date, varchar, …
- T: Nutzt einen anderen, selbst definierten Datentypen als SubType
- C: collection eines Base_type
In der Velocity-Datei wird dann zunächst für alle Typen die Forward-Deklaration angelegt, bevor im zweiten Loop die Implementierung erfolgt:
*# #* Forward-Deklaration der benutzen Objekttypen *# #foreach($row in $rows) #if($row.OBJECT_TYPE=="T" || $row.OBJECT_TYPE=="C") CREATE TYPE $row.OBJECT_VALUE; #end #if($row.OBJECT_TYPE=="C") CREATE TYPE ${row.OBJECT_VALUE}_COL IS TABLE OF $row.OBJECT_VALUE; #end #end #. Abschluss der notwendigen Forward-Deklarationen, #. um den Typen fehlerfrei erstellen zu können CREATE OR REPLACE TYPE $commonsStr.upperCase($strings.concat(["ty_", $object_name])) FORCE /* OBJECT TYPE: $object_name Beschreibung: #foreach($row in $rows) #if($row.OBJECT_TYPE=="OC") $commonsStr.replaceOnce($row.OBJECT_DESC,"--",">") #end #end #set($D="$") SVN-Info: ${D}HeadURL${D} : ${D}Id${D} Autoren: 18.03.2015 PITSS.CON Automatische Generierung LEGENDE: ... > neu, Änderung, ! Bugfix, < entfernt HISTORIE: (start table) Vers. Wann Wer Was 1.00 , 18.03.2015, PITSS.CON, *Neuerstellung (end) */ IS -- OBJECT ( #foreach($row in $rows) #if($row.OBJECT_TYPE =="R" || $row.OBJECT_TYPE =="N" || $row.OBJECT_TYPE =="T" || $row.OBJECT_TYPE =="C" ) #set($last_sort="0") #if($last_sort==$row.SORT),#end #set($last_sort=$row.SORT) #if($row.OBJECT_TYPE =="C") ${row.OBJECT_NAME} ${row.OBJECT_VALUE}_COL ${row.OBJECT_DESC} #else ${row.OBJECT_NAME} ${row.OBJECT_VALUE} ${row.OBJECT_DESC} #end#end#end ... ); / SHOW ERRORS;