Alexander (HH): DBI und Platzhalter

Beitrag lesen

Moin Moin!

MySQL-spezifisch gibt es da noch 'replace'.

qq(
REPLACE funktioniert auf exakt gleiche Weise wie INSERT. Der Unterschied besteht darin, dass, wenn ein alter Datensatz denselben Wert wie ein neuer Datensatz für einen Primärschlüssel oder einen eindeutigen Index hat, der alte Datensatz gelöscht wird, bevor der neue eingefügt wird);

Auch sehr schön, aber Du solltest Dir bei der Verwendung solcher Konstrukte bewußt sein, dass Du dich damit in eine Ecke einmauerst.

In https://forum.selfhtml.org/?t=204225&m=1382771 schriebst Du:

Wo ich gerade dranbin, ist ein modular und objektorientiert aufgebautes CMS mit integrertem Warenkorb, der so integriert ist, dass Verkaufsangebote an beliebiger Stelle eingebaut werden können ...

Ich sehe keinen Grund, das Projekt auf MySQL zu beschränken. Sicher, PHP und MySQL ist die übliche Kombination bei Massenhostern, und deswegen wäre es sicherlich sinnvoll, *auch* mit MySQL zurecht zu kommen. Aber gerade mit DBI bist Du sehr unabhängig von der DB, und warum sollte als DB nicht auch etwas vernünftiges wie PostgreSQL zum Einsatz kommen? Oder SQLite (netterweise gleich in DBD::SQLite verpackt) für kleinere Installationen ohne DB-Admin? Oder Oracle für Leute, die schon reichlich Kohle in Oracle inverstiert haben? Oder MS SQL Server für Microsoft-Buden? DB2 für IBM-Buden?

Klar, die Systeme haben alle sehr unterschiedliche SQL-Dialekte, aber der kleinste gemeinsame Nenner ist trotzdem recht groß. Der größte Unterschied ist sicherlich das automatische Generieren von IDs und anschließend das (transaktionssichere und race-freie) Ermitteln der frisch generierten ID.

Ich hab das vor etwa 10 Jahren für Oracle, SQL Server und PostgreSQL durch einen sehr dünnen "Database Abstraction Layer" erschlagen, der im wesentlichen eine DB-spezifische Sonderbehandlung für Insert-Statements gemacht hat. Der Rest war im Wesentlichen das Vermeiden von DB-spezifischer SQL-Syntax, Umschreiben von meinen abstrakten Typnamen auf DB-spezifische Typnamen[1], und die Möglichkeit, nach dem connect() der DB erst einmal ein (oder mehrere) SQL-Statement zu senden, mit dem der DB Manieren beigebracht werden (z.B. ALTER SESSION SET NLS_NUMERIC_CHARACTERS=".," für eingedeutschte Oracles).

[1] Wie heißt ein 255 Zeichen langer String, der beliebige Unicode-Zeichen aufnehmen kann? VARCHAR2(255 CHAR) bei Oracle, NVARCHAR(255) bei MS SQL Server, CHARACTER VARYING(255) oder VARCHAR(255) bei PostgreSQL -- und STRING:255 in der Anwendung, egal für welche DB. Von anderen Typen will ich gar nicht anfangen. Über diesen Mechanismus wurden übrigens auch automatisch generierte IDs behandelt, der Typ hieß unabhängig von der DB AUTONUM und wurde je nach DB auf NUMBER(10) plus Trigger plus Sequence, INTEGER IDENTITY(1,1) oder SERIAL umgeschrieben.

Das größte Problem war aber folgendes: Das Projekt fing auf Oracle an, etwas anderes war gar nicht vorgesehen, später kamen dann aber Kunden, die unbedingt den MS SQL Server einsetzen wollten (Klarer Fall von Millionen-Fliegen-Prinzip, und außerdem hatte man MS ja schon so viel gutes Geld in den Rachen geworfen ...). Oracle erlaubt pro Connection (pro $dbh) beliebig viele (oder jedenfalls deutlich mehr als eines) Statements ($sth) im aktiven Zustand zwischen execute() und finish(), der MS SQL Server nicht mehr als eines. Und das ist noch heute so, auch wenn man sich da mittlerweile mit Tricks um die Beschränkung herummogeln kann. Leider mogelt man sich dabei zwangsläufig auch gleich um große Teile des DBI herum.

Deshalb habe ich eine Zwei-Klassen-Gesellschaft eingeführt: Eine Haupt-Verbindung, auf der man Daten per DELETE, INSERT und UPDATE verändern und Transaktionen nutzen und natürlich lesen durfte, und beliebig viele Hilfsverbindungen, auf denen man nur lesen durfte. Der "Database Abstraction Layer" hat dann zwei Methoden gehabt, mit denen man sich die Haupt-Verbindung oder eine alte oder neue, benannte Hilfsverbindung holen konnte. Für alle Datenbanken außer MS SQL Server haben beide Methoden immer stumpf die selbe Verbindung geliefert.

Alexander

--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".