NAME

Dimedis::Ddl::Config - Konfiguration von Dimedis::Ddl

SYNOPSIS

Diese Dokumentation beschreibt die Datenstruktur, aus der Dimedis::Ddl den DDL Code zur Generierung von Datenbanken erzeugt.

DESCRIPTION

Ausgangsbasis ist eine Konfigurationsdatei bzw. eine Perl Datenstruktur, die üblicherweise in einer Konfigurationsdatei steht.

Diese Struktur definiert das Datenmodell zum Anlegen von Tabellen, Indices, Constraints und Fremdschlüsselreferenzen. Weiterhin können damit Änderungen an o.g. Datenbankobjekten beschrieben werden (ALTER TABLE). Hinweise dazu gibt es in einem eigenen Kapitel.

Grundstruktur

Die Konfigurations-Datenstruktur ist eine Listenreferenz. Für jede Tabelle gibt es zwei Einträge: den Namen sowie eine weitere Liste mit den Eigenschaften der Tabelle:

[
  table_a => [
    ...
  ],
  table_b => [
    ...
  ],
  ...
]

Die => Schreibweise suggeriert zwar ein Hash, es handelt sich aber um Listenreferenzen, da ein Hash die Reihenfolge der Elemente nicht erhalten würde.

Der Inhalt einer Tabellendefinition ist wiederum ein als Listenreferenz aufgeschriebenes Hash und definiert die Spalten der Tabelle, sowie Constraints, Indices etc.

KONFIGURATION ZUM ANLEGEN VON OBJEKTEN

Zunächst folgt eine Beschreibung zum Anlegen von neuen Objekten in der Datenbank. Das darauf folgende Kapitel beschreibt die Änderung von existierenden Objekten, wobei dabei aber letztlich dieselbe Syntax, erweitert um wenige Schlüsselworte, Verwendung findet.

Wichtig:

Spaltendefinitionen müssen beim Anlegen von Tabellen immer zuerst genannt werden, erst danach dürfen Primärschlüssel, Constraints etc. definiert werden. Ansonsten bricht Dimedis::Ddl mit einer Fehlermeldung ab: "missing _alter option or wrong order (specify columns first)".

Definition von Spalten

Spalten werden einfach durch ihren Namen und Typen definiert, wobei für die Typbeschreibung eine reduzierte DDL Syntax zur Verfügung steht.

Beispiel:

it_lang => [
  ni_id          => "SERIAL",
  ns_name        => "VARCHAR(30)",
  ns_iconpath    => "VARCHAR(255) NOT NULL",
  ni_default     => "NUMERIC(1) DEFAULT 0 NOT NULL",
  ns_shortcut    => "VARCHAR(4)",
],

Spaltennamen dürfen nicht mit einem Unterstrich anfangen, weil solche Bezeichner für die Definition von Primärschlüsseln, Constraints etc. reserviert sind. Mehr dazu weiter unten.

Folgende Spaltentypen stehen zur Verfügung:

  SERIAL          automatisch generierter numerischer Schlüssel
  		  (per Default NOT NULL, die Angabe von NULL/NOT NULL
		   ist nicht erlaubt)
  VARCHAR(n)      alphanumerisch mit max. n Zeichen
  CHAR(n)         alphanumerisch mit exakt n Zeichen
  INTEGER         32 Bit Integer Zahl
  NUMERIC(n[,m])  numerischer Wert mit n Stellen, davon m
                  nach dem Komma
  BLOB            Binary large object
  CLOB            Character large object
  DATE            Dimedis::Sql Datumsfeld (16 Zeichen CHAR)
  NATIVE_DATE     Datumsfeld, datenbankspezifisch. Sollte nur
                  in Ausnahmefällen verwendet werden, da Dimedis::Sql
                  es nicht unterstützt

Groß-/Kleinschreibung ist bei den Typen nicht relevant, per Konvention sollte aber Großschreibung verwendet werden.

Optionen bei der Spaltendefinition

Hinter dem Spaltentyp können mit Leerzeichen getrennt in beliebiger Reihenfolge folgende Optionen angegeben werden:

  NULL		  Spalte darf NULL werden (Default)
  NOT NULL        Spalte darf nicht NULL werden
  DEFAULT '...'   String als Defaultwert
  DEFAULT n       Zahl als Defaultwert
  DEFAULT SYSDATE Wenn die Datenbank es unterstützt, wird hier
                  das aktuelle Datum eingesetzt
  LIKE SEARCH     Gibt für ein VARCHAR Feld an, daß es LIKE
                  Suchen unterstützen muß
  CASE SENSITIVE  Wirkt sich derzeit nur bei MySQL aus. Die
  		  Spalte wird mit der BINARY Option angelegt.
		  D.h. die Sortierung erfolgt per ASCII (Umlaute
		  werden falsch einsortiert), dafür werden Indices,
		  Unique Constraints aber case sensitive.

Weitere Optionen werden nicht unterstützt. NULL bzw. NOT NULL können beide weggelassen werden, dann ist die Spalte per Default NULL definiert. NULL muß also i.d.R. nicht angegeben werden, ist aber bei ALTER TABLE Verwendung nötig, wenn eine Spalte explizit zu NULL werden soll (siehe "Konfiguration zum Ändern von Objekten").

Die LIKE_SEARCH Option ist ein Hinweis für Datenbanken, die Einschränkungen bei großen VARCHAR Feldern haben und muß bei allen Spalten gesetzt werden, über die später LIKE Suchen gemacht werden.

Definition des Primärschlüssels

Der Primärschlüssel der Tabelle wird mit dem _primary_key Schlüsselwort festgelegt:

Beispiel:

it_lang => [
  ni_id        => "SERIAL",
  ns_name      => "VARCHAR(30)",
  _primary_key => [
    on         => "ni_id",
    name       => "pk_it_lang",
  ],
],

_primary_key ist also ein Hash (das auch als Liste übergbeben werden darf) mit folgenden Schlüsseln:

on               Name der Spalte, die Primary Key sein soll
		   (mehrere Spalten mit Komma getrennt)
name             Name des dazugehörigen Constraints

Beide Schlüssel müssen angegeben werden.

Definition von Fremdschlüssel Referenzen

Fremdschlüssel werden wie folgt mit _reference oder _references definiert:

it_ticket_dump => [
  ni_id            => "SERIAL",
  ns_ticket        => "VARCHAR(14)",
  _primary_key     => "ni_id",
  _reference => [
    name           => "r_ticsto_tic",
    src_col        => "ns_ticket",
    dest_table     => "it_ticket",
    dest_col       => "ns_ticket",
    delete_cascade => 0,
  ],
],

_reference ist also ein Hash (das auch als Liste übergeben werden darf) mit folgenden Schlüsseln:

  name             Name das dazugehörigen Constraints
  src_col          Quellspalte(n) in der aktuellen Tabelle,
                   Angabe mehrerer durch Komma getrennter
		   Spaltennamen ist möglich
  dest_table       Zieltabelle
  dest_col         Spalte(n) in der Zieltabelle,
                   Angabe mehrerer durch Komma getrennter
		   Spaltennamen ist möglich
  delete_cascade   1       mit DELETE CASCADE
 		   0       ohne DELETE CASCADE
		   cyclic  nur wenn die Datenbank zyklische
		           DELETE CASCADES erlaubt
  

Die Angabe cyclic bedeutet, daß nur Datenbanken, die hier auch zyklische Referenzen unterstützen, das DELETE CASCADE verwenden. Andere Datenbanken legen diesen Constraint ebenfalls an, allerdings ohne die ON DELETE CASCADE Option.

Definition von Indices

Indices werden auch direkt in der Tabellendefinition mit _index angegeben.

Beispiel:

it_ticket_dump => [
  ni_id        => "SERIAL",
  ns_ticket    => "VARCHAR(14)",
  _primary_key => "ni_id",
  _index => [
    name   => "unq_ticsto_tic",
    on     => "ns_ticket",
  ],
],

_index ist also ein Hash (das auch als Liste übergeben werden darf) mit folgenden Schlüsseln:

name             Name des Index 
on               Spalte(n), Angabe mehrerer durch Komma
		   getrennter Spaltennamen ist möglich

Definition von Constraints

Über die Fremdschlüsselbeziehungen hinaus können Tabellen- und Unique Constraints angelegt werden, mit dem Schlüsselwort _constraint.

Beispiel:

it_lang => [
  ni_id          => "SERIAL",
  ns_name        => "VARCHAR(30)",
  ni_default     => "NUMERIC(1) DEFAULT 0 NOT NULL",
  _primary_key   => "ni_id",
  _constraint => [
    name   => "b_lang_nide",
    expr   => "ni_default IN (0,1)",
  ],
  _constraint => [
    name   => "uq_lang_name",
    unique => "ns_name",
  ],
],

_constraint ist also ein Hash (das auch als Liste übergeben werden darf) mit folgenden Schlüsseln:

  name             Name des Constraints
  expr             Ausdruck, der wahr sein muß
  unique           Spalte(n), die unique sein sollen, Angabe
  		   mehrerer durch Komma getrennter Spaltennamen
		   ist möglich

expr und unique dürfen nicht gleichzeitig angegeben werden. Bei den Constraint Ausdrücken ist zu beachten, daß alle Datenbanken diese unterstützen müssen.

Datenbankspezifische Angaben

Bestimmte Datenbankfunktionen werden von Dimedis::Ddl nur in Form von datenbankspezifischen Erweiterungen unterstützt. Dabei werden Einstellungen vorgenommen, die nur von dem Treiber der entsprechenden Datenbank verarbeitet werden.

Diese Definitionen sind nach folgendem Schema benannt:

_db_DATENBANK => [
  ...
],

wobei DATENBANK durch die jeweilige Zieldatenbank ersetzt wird. Derzeit wird dies nur für Oracle genutzt, um tabellenübergreifende Klauseln anzugeben:

  _db_Oracle => [
    table => "lob (nb_blob) store as (
    		storage (initial 1M next 1M pctincrease 0) 	
	        chunk 4 nocache logging
	      )"
  ],

D.h. am Ende der Tabellendefinition wird der entsprechende String angehängt, um z.B. Storage Definitionen für Blobs vorzunehmen (wie in obigem Beispiel).

Nur Type Hash Generierung

Mit der Definition

_type_hash_only

wird kein DDL Code für diese Tabelle generiert, sondern lediglich ein entsprechender Type Hash Eintrag.

KONFIGURATION ZUM ÄNDERN VON OBJEKTEN

Das Format zur Änderung von Objektdefinitionen ist mit dem zum Anlegen identisch, ergänzend gibt es lediglich das Schlüsselwort _alter, das definiert, ob die folgenden Definitionen hinzugefügt, geändert oder gelöscht werden sollen.

Beispiel:

it_lang => [
  _alter => "add",

  ns_foo => "VARCHAR(32) NOT NULL",

  _index => [
    name   => "lang_foo_idx",
    on     => "ns_foo",
  ],

  _alter   => "modify",
  ns_bar   => "VARCHAR(100)",
  
  _alter   => "drop",
  ns_baz   => "VARCHAR(16) NOT NULL",
  _constraint => "b_foo",
  _primary_key => [ name => 'pk_foo' ],
],

it_foo => [
  _alter => "drop_table"
],

Im Beispiel wird also eine neue Spalte ns_foo samt Index angelegt, die existierende ns_bar im Typ geändert. Die Spalte ns_baz sowie der Constraint b_foo und der Primary 'pk_foo' werden gelöscht. Weiterhin wird die Tabelle it_foo gelöscht.

Auf dieser Art und Weise können Spaltentypänderungen genauso durchgeführt werden, wie Änderungen an Constraints, Referenzen und Indices, dabei spielt es keine Rolle ob diese hinzugefügt, geändert oder gelöscht werden.

Hinweise zum Ändern von Spalten

Die Typangabe bei einer Spaltenänderung (_alter => "modify") führt zwei neue Schlüsselwörter KEEP und ALTER ein, die sich auf den NULL/NOT NULL Constraint der Spalte beziehen. Bei einer Spaltenänderung muß immer NULL bzw. NOT NULL angegeben werden (es sei denn es handelt sich um den SERIAL Datentyp, dieser ist immer NOT NULL), in Kombination mit KEEP, wenn die Spalte vorher denselben Zustand hatte bzw. mit ALTER, wenn sich der Zustand nun ändern soll.

Im obigen Beispiel wird also ns_foo von NULL zu NOT NULL geändert. Bei ns_bar bleibt der NULL Constraint so erhalten, wie er vorher war.

Diese explizite Angabe ist notwendig, da einige Datenbanken eine Wiederholung eines existierenden NULL/NOT NULL Constraints nicht erlauben und andere stets eine relative Angabe erwarten, bzw. nur NULL/NOT NULL angegeben werden darf, wenn sich der Constraint auch tatsächlich ändern soll.

Hinweise zum Ändern von Indices, Constraints und Referenzen

Wenn hier ein modify durchgeführt wird, so wird DDL Code erzeugt zum Löschen und neu Anlegen des entsprechenden Objektes. Eine direkte Änderung ist also nicht möglich. Dies muß berücksichtigt werden, weil sich z.B. Referenzen nicht unbedingt löschen lassen, wenn noch Daten existieren, die diese verwenden.

Hinweise zum Löschen von Indices, Constraints und Referenzen

Wenn ein Index oder Constraint gelöscht werden sollen, so reicht es bei dem entsprechenden Hash nur den name Schlüssel anzugeben. Alle anderen Schlüssel werden in diesem Fall nicht benötigt und ignoriert.

Bei Referenzen hingegen, ist stets die vollständige Angabe aller Parmeter erforderlich.

Hinweise zum Löschen von Tabellen

Eine Tabelle wird mit der Anweisung _alter => "drop_table" gelöscht. In diesem Fall dürfen keine anderen Angaben innerhalb dieser Tabellendefinition gemacht werden.

Mischung von Änderungs- und Erstellungs-Definitionen

Innerhalb einer DDL Konfiguration dürfen sowohl Änderungsdefinitionen als auch solche zum Erstellen gemischt werden. Sobald das Schlüsselwort _alter in einer Tabellenkonfiguration gefunden wird, werden alle folgenden Definitionen als Änderungen aufgefaßt. Wird das Schlüsselwort nicht verwendet, so handelt wird die entsprechende Tabelle inkl. angegebener Indices etc. neu angelegt.

Sonderfall: Löschen eines SERIAL Primary Key Constraints

Ein Primary Key Constraint auf einem SERIAL kann nicht einfach wie folgt gelöscht werden:

it_foo => [
  _alter       => 'drop',
  _primary_key => [ name => 'pk_foo' ]
]

Dies wird von MySQL nicht unterstützt. Zunächst muß eine normale, nicht-SERIAL Spalte daraus gemacht werden, erst danach darf der Primary Key Constrint entfernt werden. Richtig ist also:

it_foo => [
  _alter       => 'modify',
  ni_id        => 'integer keep not null',

  _alter       => 'drop',
  _primary_key => [ name => 'pk_foo' ]
]

Damit funktioniert es mit allen Datenbanken.

AUTOR

Joern Reder <joern@dimedis.de>

COPYRIGHT

Copyright (c) 2001-2003 dimedis GmbH, All Rights Reserved

SEE ALSO

dddl, Dimedis::Ddl, Dimedis::Sql

1 POD Error

The following errors were encountered while parsing the POD:

Around line 106:

Non-ASCII character seen before =encoding in 'üblicherweise'. Assuming CP1252