20 Stimmen

Gibt es so etwas wie portables SQL?

Obwohl es einen SQL-Standard gibt, ist es meiner Erfahrung nach ziemlich schwierig, SQL zu schreiben, das unverändert mit einer großen Anzahl von RDBMS funktioniert.

Daher würde ich gerne wissen, ob es eine Teilmenge von SQL (einschließlich DDL, Schemata usw.) gibt, von der bekannt ist, dass sie auf allen wichtigen RDBMS funktioniert, einschließlich PostgreSQL, MySQL, SQL Server und nicht zuletzt Oracle. Welche Fallstricke sollten beim Schreiben von portablem SQL vermieden werden?

Gibt es übrigens ein Projekt, dessen Ziel es ist, eine gültige Teilmenge von SQL in die spezifischen Dialekte zu übersetzen, die von all diesen Anbietern verwendet werden? Ich weiß, dass Hibernate und andere ORM-Systeme dies tun müssen, aber ich will kein ORM, ich will SQL direkt in die Datenbank schreiben.

Danke!

5voto

a_horse_with_no_name Punkte 489934

Das Problem ist, dass einige DBMS sogar die einfachsten Standards ignorieren (z. B. Anführungszeichen oder String-Verkettung).

Das Folgende (100% ANSI SQL) läuft also nicht auf jedem DBMS:

UPDATE some_table
    SET some_column = some_column || '_more_data';

Und dabei denke ich noch nicht einmal an fortgeschrittenere SQL-Standards wie rekursive gemeinsame Tabellenausdrücke (selbst diejenigen, die sie unterstützen, halten sich nicht immer daran) oder Windowing-Funktionen (einige implementieren nur eine sehr kleine Teilmenge, andere unterstützen nicht alle Optionen).

Was die DDL betrifft, so gibt es ein Problem mit den Datentypen. DATE ist nicht überall gleich, genauso wie TIMESTAMP . Nicht jedes DBMS hat eine BOOLEAN Typ oder TIME Typ.

Wenn es um Beschränkungen oder Bereiche geht, gibt es noch mehr Unterschiede.

Kurz und gut: Es sei denn, Sie haben wirklich, wirklich DBMS-unabhängig sein müssen, sollten Sie sich nicht damit befassen.

Dennoch: Wenn Sie die Wahl zwischen einer proprietären und einer Standardsyntax haben, wählen Sie die Standardsyntax ( OUTER JOIN gegen (+) o *= , decode gegen CASE , nvl vs. coalesce und so weiter).

2voto

Solomon Rutzky Punkte 44018

Innerhalb jedes RDBMS sollte alles, was als ANSI-kompatibel aufgeführt ist, für alle gleich sein, da dies der wahre Standard ist. Wenn Sie jedoch nur ANSI-konforme (d.h. portable) Daten verwenden, verlieren Sie die optimierten, herstellerspezifischen Funktionen. Außerdem bedeutet die Tatsache, dass PostgreSQL eine ANSI-Funktion implementiert, nicht, dass sie auch in jedem anderen RDBMS verfügbar ist (aber wenn sie verfügbar ist, dann sollte sie genauso funktionieren).

Ich persönlich sehe keinen Wert in wirklich portierbarem SQL-Code oder einem Projekt zur Normalisierung auf einen kleinsten gemeinsamen Nenner, da jedes RDBMS anders optimiert ist. Es gibt keine gemeinsame Anwendungssprache. WENN Sie C# verwenden, dann würden Sie nicht Dinge verwenden wollen, die nur in PHP oder JAVA zu finden sind. Nehmen Sie also einfach die Plattform an, auf der Sie sich befinden :).

Bearbeiten: Wenn Sie eine Anwendung schreiben, die mit mehreren verschiedenen RDBMS verbunden werden kann, müssen Sie wahrscheinlich für jede bestimmte Plattform das passende SQL finden, so wie es die Autoren der einzelnen ORMs tun mussten.

1voto

Adam Robinson Punkte 176996

Einfache Abfragen sind fast immer übertragbar. Leider ist die Liste der SQL-Anbieter, die Sie angegeben haben, sehr unterschiedlich, was die Einhaltung von Standards angeht. MS SQL Server steht an der Spitze der von Ihnen genannten Anbieter, was die Einhaltung der ANSI-SQL-Standards angeht, und sowohl MySQL als auch Oracle sind notorisch schlecht, wenn es um die Einhaltung von Standards geht. Das soll natürlich nicht heißen, dass sie schlechte RDBMS-Engines sind oder dass man mit ihnen keine leistungsfähigen Abfragen schreiben kann, aber die Einhaltung der Standards ist nicht gerade das, wofür sie bekannt sind.

Beachten Sie, dass Sie einige große RDBMS-Anbieter in dieser Liste ausgelassen haben, nämlich Sybase und IBMs DB2. Diese beiden sind in der Regel standardkonformer als die anderen, wenn Sie mich fragen.

1voto

onedaywhen Punkte 52850

Die Vorstellung, dass ich SQL-Code für ein Produkt schreiben und erwarten kann, dass er in einem anderen ohne Änderungen funktioniert, ist ein unmöglicher Traum.

Ich denke eher, dass "Portabilität" ein Maß dafür ist, wie einfach es ist, Code auf ein anderes SQL-Produkt oder, was entscheidend ist, auf eine spätere Version desselben SQL-Produkts zu übertragen, wobei zu beachten ist, dass etablierte SQL-Produkte dazu neigen, sich zu bewegen zu die SQL-Standards (z.B. die SQL-92's UPDATE skalare Unterabfragen erfordert und daher langwierig ist, hat SQL Server schon früh proprietäre JOIN..FROM Syntax dann für SQL Server 2008 eine MERGE Syntax, die Folgendes unterstützt y erweitert Standard SQL's MERGE ).

Als Faustregel gilt: Verwenden Sie Standard-SQL-Code, wenn Ihr SQL-Produkt ihn unterstützt (z. B. CURRENT_TIMESTAMP anstelle der SQL Server-internen getdate() ), andernfalls bevorzugen Sie proprietären Code, der sich leicht in Standard-SQL-Code abbilden lässt (z. B. SQL Server's SUBSTRING() lässt sich leicht auf Standard SQL abbilden SUBSTRING() unter Verwendung eines Makros). Beachten Sie, dass einige Funktionen außerhalb des SQL-Standards den SQL-Produkten gemeinsam sind (z.B. haben die meisten/alle eine MOD() Funktion oder Operator).

1voto

user2625000 Punkte 11

Ich entwickle Webanwendungen mit Alpha Five, das über eine Funktion namens "Portable SQL" verfügt. Es gibt etwa 200 "Portabilitätsfunktionen". Wenn ich eine Portabilitätsfunktion verwende, wird sie automatisch in Native SQL umgewandelt, damit sie in die von mir verwendete Engine passt.

Wenn ich also schreibe "SELECT now() FROM clients", wobei now() eine Portabilitätsfunktion ist, wird diese Syntax automatisch in die Muttersprache umgewandelt, je nachdem, welche Sprache ich gerade verwende. Es werden 22 verschiedene SQL-Engines unterstützt.

  • DB2-SELECT CURRENT TIMESTAMP AS Expr1 FROM client
  • MYSQL-SELECT Now() AS Expr1 FROM client
  • MSSQL-SELECT CURRENT_TIMESTAMP AS Expr1 FROM client
  • SYBASE-SELECT getdate() AS Expr1 FROM client
  • ODBC-SELECT {fn Now()} AS Expr1 FROM client

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X