SQL – subtile Unterschiede in Serverfunktionen Teil 1

Oft hat man schon teilweise jahrelang mit einer bestimmten Serverfunktion gearbeitet, um dann durch Zufall herauszufinden, es gibt auch eine andere, die zumindest scheinbar genau das Gleiche erledigt. Ein paar dieser AHA-Erlebnisse und einen kurzen Überblick über Ähnlichkeiten und Unterschiede gibt es hier:

Plus oder CONCAT? CONCAT oder CONCAT_WS? PARSE, CAST oder CONVERT? Ein Kurzüberblick über die Unterschiede und einfache Beispiele.


+, CONCAT und CONCAT_WS

 

Oft wird zum Zusammenfügen von Strings einfach ein Plus-Zeichen verwendet. In vielen Fällen bekommen wir damit auch exakt das gleiche Ergebnis heraus, wie mit CONCAT. Wo liegen also die Unterschiede?

 

Zum Testen erstellen wir erst eine Demo-Tabelle mit Vorname, Nachname und Titel und geben ein paar Testwerte ein:

CREATE TABLE demo (FirstName varchar(25), LastName varchar(25), Title varchar(10))

 

INSERT INTO demo (FirstName, LastName, Title)

VALUES        ('John', 'Doe', NULL),

              ('Jane', 'Doe', 'Dr.'),

              ('Robin', 'Hood', 'Mr.')

Wollen wir nun Vor- und Nachname in einer Spalte als FullName ausgeben, könnten wir das Plus-Zeichen oder CONCAT verwenden:

SELECT FirstName + ' ' + LastName AS FullName

FROM demo

 

     -- oder:

 

SELECT CONCAT(FirstName, ' ', LastName) AS FullName

FROM demo

Wir haben hier auch jeweils ein Leerzeichen zwischen Vor- und Nachname eingefügt.

In beiden Fällen ist unser Ergebnis gleich:

Wollen wir aber den Titel mit ausgeben, sieht es etwas anders aus:

SELECT Title + ' ' + FirstName + ' ' + LastName AS FullName

FROM demo

Ergebnis:

 

Jede mathematische Operation mit NULL führt wieder zu NULL. Da für den ersten Eintrag kein Titel existiert, führt unser „NULL + Text“ zu NULL.

Mit CONCAT funktioniert es, ist aber noch nicht ideal:

SELECT CONCAT(Title, ' ', FirstName, ' ', LastName) AS FullName

FROM demo

Ergebnis:

 

Immerhin steht der Text da; schaut man allerdings genauer hin, fällt auf, dass unser John Doe etwas eingerückt ist, denn hier haben wir davor ein Leerzeichen eingefügt. Unsere CONCAT-Funktion hat außerdem den Nachteil, dass wir zwischen jeden Eintrag händisch ein Leerzeichen setzen müssen.

Dafür gibt es eben noch CONCAT_WS. Das „WS“ steht für „with separator“; wir können damit also einmal ein Trennzeichen angeben, dass dann zwischen alle einzelnen Einträge gesetzt wird:

SELECT CONCAT_WS(' ', Title, FirstName, LastName) AS FullName

FROM demo

Ergebnis:

Damit haben wir vor „John“ kein Leerzeichen, denn die Leerzeichen werden nur als Trennzeichen gesetzt. NULL wird korrekt als „nicht vorhanden“ eingestuft und bekommt somit auch keinen Separator.

Auch, wenn wir mehrere Einträge durch einen Separator trennen wollen, empfiehlt sich die Verwendung von CONCAT_WS, um nicht jedes Trennzeichen händisch angeben zu müssen; der gewünschte Separator wird nur einmal am Anfang angegeben:

SELECT CONCAT_WS(' ', 'Ich', 'weiß,', 'dass', 'ich', 'nichts', 'weiß.') AS Zitat

Ergebnis:

 


PARSE, CAST oder CONVERT?

 

CAST und CONVERT sind die beiden schon länger bekannten Serverfunktionen zum Konvertieren eines Datentyps in einen anderen. Die Syntax bei den beiden ist etwas anders:

 

-- mit CAST:

SELECT CAST('123' AS int) + 2 AS Ergebnis

 

-- mit CONVERT

SELECT CONVERT(int, '123') + 2 AS Ergebnis


Beide geben aber das gleiche Ergebnis aus:

Welche der beiden zu bevorzugen ist, ist eine der vielen Streitfragen in SQL, bei der auch mit Begriffen wie bessere Lesbarkeit argumentiert wird (und das sieht jeder ein bisschen anders). Auch die Performance kann situationsabhängig variieren und muss von Fall zu Fall getestet werden; die Performance-Unterschiede zwischen den beiden scheinen aber größtenteils vernachlässigbar zu sein.

Zwei erwähnenswerte Unterschiede gibt es zwischen diesen beiden Serverfunktionen:

  1. CAST ist ANSI, CONVERT ist serverspezifisch.
  2. CONVERT akzeptiert einen Style-Parameter, CAST nicht.

 

Über den Style-Parameter von CONVERT können wir beim Arbeiten mit Datum dafür sorgen, dass es in menschenleserlichem Format ausgegeben wird. Setzen wir als Style-Parameter 104, erhalten wir das Datum in deutscher Schreibweise:

SELECT CONVERT(varchar, GETDATE(), 104) AS Datum

Ergebnis:

 

 CAST allein kann das nicht; mit CAST können wir nur Datentypen konvertieren, keinen Style angeben.

 

PARSE ist ein jüngerer Verwandter der beiden. Auch mit PARSE können wir Datentypen konvertieren, und im ersten Moment scheint es so, als würden PARSE und CAST gleich funktionieren.

PARSE ist allerdings mit Vorsicht zu genießen. Ein Auszug aus der Microsoft-Dokumentation gibt uns einige Gründe an, warum: 

„Verwenden Sie PARSE nur, um eine Zeichenfolge in ein Datum und eine Uhrzeit oder in eine Zahl zu konvertieren. Für die allgemeine Typkonvertierungen sollten Sie auch weiterhin CAST oder CONVERT verwenden. Bedenken Sie, dass die Analyse des Zeichenfolgenwerts mit gewissen Leistungseinbußen verbunden ist.“

Übersetzt: Wenn überhaupt, dann ist es auch noch langsamer als die anderen beiden.

Und:

 „Für PARSE muss die .NET Framework-Common Language Runtime (CLR) vorhanden sein.“

 

Genaueres gibt es natürlich in der Microsoft-Dokumentation.


Wozu gibt es PARSE dann überhaupt? PARSE kennt auch einen Culture-Parameter (zumindest, wenn CLR vorhanden ist). Das kann für das Datum praktisch sein, oder für Text zu Zahl:

SELECT PARSE('€123,45' AS money USING 'de-DE') AS Preis

Ergebnis:

 

CAST hingegen würde bei diesem Beispiel versagen:

SELECT CAST('€123,45' AS money) AS Preis

Ergebnis:

 

Trotzdem: Wenn wir es nicht für irgendeinen Sonderfall brauchen, sollten wir lieber bei CAST und CONVERT bleiben.

Auch mit FORMAT können wir über den Culture-Parameter eine schöne Datums-Formatierung erreichen, allerdings kann FORMAT für uns keine Konvertierung vornehmen. Mehr zum Thema Datum und Datumsformatierung gibt es hier.

 

Mehr dazu gibt es auch in unseren Kursen!

In der Zwischenzeit: Viel Spaß beim Ausprobieren!

Kommentare sind geschlossen