Anfängerfragen zu Schemas und Strukturen

Hi,

ich wurde überzeugt, von MySQL auf PostgreSQL umzusteigen… Ich war ziemlich schnell sehr begeistert, allerdings habe ich aufgrund der Komplexität von PostgreSQL einige Fragen, die ich nicht mithilfe der Dokumentation beantworten konnte:

Die erste Frage ist zum Thema Schemas.

Von MySQL bin ich es gewohnt, eine Datenbank pro Projekt zu benutzen. Da ich auf meinem Server mehrere Nutzer habe, folgte ich bei den Namen der Konvention, dass die Dantenbanken username_projekt hießen. Der Nachteil war, dass ich mich als Administrator darum kümmern musste, den Nutzern Datenbanken anzulegen, was unter MySQL sehr nervig ist.
Unter PostgreSQL wäre es ja möglich, dass ich einfach eine Datenbank pro Benutzer anlege und die Benutzer dann ihre Projekte auf Schemas verteilen, die sie sich selbst anlegen können. Ist das eine sinnvolle Vorgehensweise? Ich sehe sonst für mich keinen Nutzen bei Schemas, da nur ein Benutzer pro Datenbank Zugriff haben muss. Die Alternative wäre, dass ich den Benutzern das Recht gebe, Datenbanken zu erzeugen, was unter PostgreSQL möglich ist. Was ist generell sinnvoller?

Dann habe ich noch eine Frage zur Verwaltung von Tabellenstrukturen. Bei meinen MySQL-Projekten hatte ich für jede Datenbank eine Datei schema.sql, in der folgende Anweisungen standen:

DROP TABLE IF EXISTS tabelle_1;
CREATE TABLE tabelle_1(...);

DROP TABLE IF EXISTS tabelle_n;
CREATE TABLE tabelle_n(...);

Wenn ich nun während der Entwicklungsphase etwas an der Struktur geändert habe, konnte ich die Datei einfach von MySQL ausführen lassen und hatte eine frische Datenbank. In PostgreSQL 8.1 gibt es “IF EXISTS” noch nicht und da pgAdmin Dateien als Transaktion ausführt, sehe ich keine Möglichkeit, die Struktur auf eine einfache Art zu ändern - Bei DROP TABLE-Anweisungen würde beim ersten Mal eine Fehlermeldung kommen und die Transaktion abbrechen; ohne DROP würde die Meldung kommen, weil die Tabelle schon existiert.
Wie handhabt ihr das während der Entwicklung? Wenn die Struktur einmal steht, erzeuge ich weitere Dateien, zum Beispiel migrate_1.sql, die dann ALTER TABLE-Anweisungen enthält.

Gruß

Folke

Beantworten wir die Fragen mal der Reihe nach:

Schemas: du wirst bei Mysql zwar keine Schemas kennen, aber wenn ich dir die (Work|Würg)arounds nenne, die dort gehandhabt werden, wird der Sinn vielleicht klarer. Mysql behandelt einzelne Datenbanken wie Schemata, kann allerdings keine gemischten Anfragen über Datenbankgrenzen hinweg durchführen. Über Schemagrenzen geht dies in PG jedoch ganz einfach.
Und noch etwas anderes kennst du vielleicht: viele Webprojekte liefern in ihrer Config ein Prefix mit, was dann vor alle Tabellen dieses Projektes gesetzt wird. Sinn ist es, mehrere Projekte in einer Datenbank halten zu können (in einer Hostingumgebung z.B.). Nun, in PG sagst du einfach, in welchem Schema du deine Daten haben möchtest, setzt deinen search_path zu Anfang einmal passend und schon bist du alle weiteren Probleme los :wink:
Nicht zuletzt bleibt natürlich der von dir angesprochene Vorteil, das sich jeder Nutzer in seiner DB eigene Schemas anlegen kann. Davon, das jeder User gleich Adminrechte in der DB bekommt, halte ich wenig und das macht auch keinen Sinn.

Scripte: Nun, diese sind in PG auch möglich, wie genau PGAdmin das handhabt, weiss ich allerdings nicht. Ich gebe zu, ich arbeite gern auf der Console. Gibt es dort keine Möglichkeit, einfach eine Datei zum Ausführen anzugeben? Ein DROP TABLE IF EXISTS gibt es (noch) nicht, kommt wohl in der kommenden Version (oder wurde es schon in 8.2 eingebaut, weiss ich gerade nicht auswendig).
Allerdings kann man sich mit einem kleinen Workaround behelfen, ein Beispiel liefert dir der Workshop, den wir in Dresden und Chemnitz gehalten haben: http://pgug.de/documents/Chemnitzer_Linuxtage/2006/pgsql-2006-03-04-4.php
Dort wird eine Tabelle innerhalb einer Funktion gelöscht und die ev. auftretende Fehlermeldung abgefangen.

Die Handhabung sieht bei mir etwas anders aus, wenn ich entwickle: ich habe mindestens 2, jedoch meistens mehrere Dateien. Davon ist eines in der Regel ein drop.sql, das die Löschbefehle in passender Reihenfolge enthält. Die anderen sind .sql Dateien, die mir ein Makefile zu einer Datei zusammensetzt, dort stehen ganz oben die Lösch- und dann die Befehle zum erzeugen. Wenn ich Sachen wie ein Drop Table brauche, steht in einer der Dateien auch eine passende Funktion, die ich temporär für die Zeit des Neu erstellens anlege und zum Schluss wieder lösche. Als Regel gilt bei mir: es dürfen beim Erstellen keine Fehler auftreten.

Moin.

Erst mal Glückwunsch zu Deiner Entscheidung :wink:

Neben dem, was ads schon sagte, kannst Du z.B. diese kleine Funktion von http://a-kretschmer.de/drop_if_exists.sql verwenden, um Tabellen zu löschen. Allerdings funktioniert das nicht mit voll ausgeschriebenen Tabellennamen, also in der Form schema.table und auch nicht, wenn in unterschiedlichen Schemas mehrere Tabellen mit diesem Namen existieren.
Das ließe sich aber relativ schnell noch erweitern, falls Du das brauchst. Ist also mehr als Anregung zum basteln zu verstehen :wink:

Ansonsten ist der Weg, den ads und ich in dem von ads angesprochenem Workshop gemacht haben, auch eine praktikable Lösung, die man schnell zu einer passenden Funktion erweitern könnte.

Hi,

vielen Dank für die Informationen. Ich werde für jeden User eine Datenbank anlegen, den Rest können sie dann selber mit Schemas lösen.
Zum Löschen werde ich jetzt auch einfach ein Makefile benutzen, danke für den Tipp.

Gruß

Folke