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:
- CAST ist ANSI, CONVERT ist serverspezifisch.
- 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!