Funktionen im SELECT-Clause (Single-Row-Functions)
https://bildung.social/@oerinformatik/112633708392604185
https://oer-informatik.de/sql-dml-singlerowfunctions
SQL, DQL, Skalare Funktionen, Single-Row-Functions, Zeichenkettenfunktionen, Datumsfunktionen, TIMESTAMPDIFF, CONCAT, MariaDB, SQL Server
tl/dr; (ca. 12 min Lesezeit): In der Projektion eines
SELECT-Statements können Funktionen genutzt werden, die skalar oder aggregierend sind, die Zahlen, Zeichenketten, Datumswerte oder auch die Ablaufsteuerung betreffen. Dieser Artikel gibt eine kurze Übersicht für MariaDB/MySQL und andere DBMS und zeigt typische Anwendungen: Alter berechnen, Nummern zerlegen, Namen kürzen [AI-Assisted]. (Zuletzt geändert am 28.10.2026)
Dieser Artikel ist Teil einer Artikelreihe über SQL-Abfragen: Selektion und Projektion / Sortieren und Begrenzen (ORDER BY, LIMIT) / Funktionen im SELECT (Single-Row-Functions) / Fallunterscheidungen und NULL (CASE, COALESCE) / Aggregatfunktionen und Gruppierung / Abfragen über mehrere Tabellen (JOIN) / Übungsaufgaben: einfache Abfragen, Aggregatfunktionen, JOIN, Rechnungsdatenbank (gemischt)
Schon fit in diesem Thema? Nutze die Kann-Liste und die Leitfragen unter dem Artikel als Checkliste, ob Du die relevanten Kompetenzen bereits hast.
Dieser Artikel baut auf der Kann-Liste des Artikels Selektion und Projektion auf.
Als SQL-Grundlagen kann ich nach Durchlesen des Artikels…
… skalare (Single-Row-) Funktionen von Aggregatfunktionen unterscheiden.
… Werte in der Projektion berechnen und mit
ROUNDrunden.… Zeichenketten mit
LEFT,RIGHT,SUBSTRING,CONCAT,CHAR_LENGTH,UPPER/LOWERundTRIMbearbeiten, z. B. Nummern zerlegen oder Namen abkürzen.… mit
CURDATE(),YEAR(),MONTH(),HOUR(),DATEDIFFundTIMESTAMPDIFFDatumsteile, Differenzen und das Alter berechnen und mitDATE_FORMATformatieren.
Darüber hinaus kann ich als SQL-Expertenwissen…
… Funktionsnamen und Parameterreihenfolgen zwischen MariaDB, SQL Server, PostgreSQL und SQLite übertragen (z. B.
DATEDIFF).… erklären, warum Funktionen auf Spalten in der
WHERE-Bedingung einen Index unbrauchbar machen können.
Unterschiedliche Arten von Funktionen in SQL-Statements
Unterscheidung 1: Liefern die Funktionen bei mehrmaligem Ausführen immer dasselbe Ergebnis?
| deterministisch | nicht deterministisch |
|---|---|
| gleicher Eingabewert = gleiches Ergebnis | gleiche Parameter = ggf. unterschiedliche Ergebnisse |
Beispiel: ROUND(preis, 2), UPPER(name) |
aktuelle Zeit NOW(), Zufallszahl RAND() |
(Ein Unterpunkt wäre hier noch die Idempotenz (idempotence): Die Anweisung UPDATE konto SET stand = stand + 1 ist zwar deterministisch, liefert aber bei mehrmaliger Ausführung andere Ergebnisse als bei einmaliger Ausführung; UPDATE konto SET stand = 0 ist dagegen idempotent.)
Unterscheidung 2: Beziehen sich die Funktionen auf unterschiedliche Datensätze?
| Aggregierende Funktionen | Skalare Funktionen |
|---|---|
| Sogenannte multi row functions werten Attributwerte spaltenweise aus. Details dazu in diesem Artikel zu GROUP-Functions |
Das Gegenteil sind single row functions, die lediglich Attributwerte innerhalb eines Datensatzes auswerten. |
max(bruttokosten)Gibt das Maximum aller Werte dieser Spalte aus |
(anzahl*(preis-rabatt))*mwst Berechnet für einen Datensatz (eine Zeile) einen Wert |
Der Unterschied an einem Beispiel: Skalare Funktionen liefern je Eingabezeile eine Ergebniszeile, Aggregatfunktionen fassen alle Zeilen zu einer zusammen.
Skalare Funktionen
Skalare Funktionen dürfen überall stehen, wo ein Wert erwartet wird: in der Projektion, in WHERE und in ORDER BY. Ein Ergebnis bekommt mit AS einen sprechenden Namen:
SELECT artikelnr, ROUND(netto_preis * (1 + mwst_satz / 100), 2) AS brutto
FROM artikel
WHERE ROUND(netto_preis * (1 + mwst_satz / 100), 2) > 1000
ORDER BY brutto DESC;Den Alias brutto kennt ORDER BY, in WHERE muss der Ausdruck wiederholt werden, weil WHERE vor der Projektion ausgewertet wird.
Einteilung der Funktionen:
Numerische Funktionen
Zeichenkettenfunktionen
Datums- und Zeitfunktionen
Ablaufsteuerungsfunktionen
Numerische Funktionen
| Funktion | MSSQL | MySQL/MariaDB | OracleDB | PostgreSQL | SQLite |
|---|---|---|---|---|---|
| Runden | ROUND(numeric_exp, integer_exp) |
ROUND(zahl, stellen) |
ROUND(n, s) |
round(n, s) |
ROUND(X, Y) |
| Ab-/Aufrunden auf ganze Zahl | FLOOR, CEILING |
FLOOR, CEIL |
FLOOR, CEIL |
floor, ceil |
floor, ceil (ab 3.35) |
| Ganzzahliger Rest | % |
MOD(a, b), % |
MOD(a, b) |
mod(a, b), % |
% |
| Typumwandlung | CAST(x AS int) |
CAST(x AS UNSIGNED), CAST(x AS DECIMAL(10,2)) |
CAST(x AS NUMBER) |
CAST(x AS integer), x::integer |
CAST(x AS INTEGER) |
| Gleitkommazahl formatiert ausgeben | FORMAT(value, format) |
FORMAT(zahl, stellen [, 'de_DE']) |
printf('%.2f', x) |
||
| Dokumentation / Übersicht Berechnungsfunktionen (Link) | MS Doc zu numerischen Funktionen MS Doc zu Formatierungsfunktionen, T-SQL Doc | MySQL Doc zu numerischen Funktionen | Datumsfunktionen, Hauptfunktionen |
Zeichenkettenfunktionen
| Funktion | MSSQL | MySQL/MariaDB | OracleDB | PostgreSQL | SQLite |
|---|---|---|---|---|---|
| Zeichenkettenlänge Anzahl der Zeichen |
LEN (string_exp) |
CHAR_LENGTH(str) |
char_length ( text ) |
LENGTH |
|
| Zeichenkettenlänge in Byte |
DATALENGTH (string_exp) |
LENGTH(str) |
octet_length ( text ) |
||
| Substring rechts | RIGHT(RTRIM(str), len) |
RIGHT(str,len) |
right(str, len) |
SUBSTR(X, -Y) |
|
| Substring links | LEFT (str, len) |
LEFT(str,len) |
left(str, len) |
SUBSTR(X, 1, Y) |
|
| Substring mitte | SUBSTRING (expression, start, length) |
SUBSTRING(str, pos [, len]) (Synonym SUBSTR) |
substring(str FROM start FOR count) |
SUBSTR(X, Y, Z) |
|
| Position eines Substring finden | PATINDEX ('%pattern%', expression) |
INSTR(str,substr)LOCATE(substr,str [,pos]) |
position ( substring text IN string text ) |
INSTR |
|
| Substring in Ausgabe ersetzen | REPLACE (string_exp, string_pattern, string_replacement) |
REPLACE(str, from_str, to_str) |
REPLACE |
||
| Zeichenketten zusammenführen | CONCAT (string_value1, string_value2, ...) |
CONCAT(str1,str2,...)(liefert NULL, sobald ein Argument NULL ist; CONCAT_WS(trenner, …) überspringt NULL) |
str1 \|\| str2 |
concat(…), str1 \|\| str2 |
str1 \|\| str2 |
| Groß-/Kleinbuchstaben | UPPER, LOWER |
UPPER, LOWER |
UPPER, LOWER |
upper, lower |
UPPER, LOWER |
| Whitespaces entfernen | TRIM (string_exp)LTRIM (string_exp)RTRIM (string_exp) |
TRIM([{BOTH \| LEADING \| TRAILING} [remstr] FROM] str)LTRIM(str)RTRIM(str) |
LTRIM, RTRIM, TRIM |
||
| Mit RegEx suchen | REGEXP_LIKE(text, muster) (ab SQL Server 2025) |
WHERE name REGEXP '^H.*-.*' |
REGEXP_LIKE(text, muster) |
WHERE regexp_like( text, pattern [, flags]) |
|
| Mit RegEx ersetzen | REGEXP_REPLACE (ab SQL Server 2025) |
REGEXP_REPLACE(text, muster, ersatz) |
REGEXP_REPLACE |
regexp_replace ( text, pattern, replacement) |
|
| Dokumentation / Übersicht Stringfunktionen (Link) | MS Doc | MySQL Doc | PostgreSQL-Doc | SQLite Doc |
Beispielabfragen zur Zeichenmanipulation:
SELECT LEFT('Max Mustermann', 3) AS links, -- 'Max'
RIGHT('Max Mustermann', 5) AS rechts, -- 'rmann'
SUBSTRING('RE-2026-00412', 4, 4) AS jahr, -- '2026'
CONCAT('Max', ' ', LEFT('Mustermann', 1), '.') AS kurz; -- 'Max M.'Die Länge zählt CHAR_LENGTH in Zeichen, LENGTH in Byte – bei Umlauten in UTF-8 ein Unterschied:
SELECT CHAR_LENGTH('Jörg') AS zeichen, -- 4
LENGTH('Jörg') AS bytes; -- 5 (ö belegt in UTF-8 zwei Byte)Die Position eines Teilstrings liefern LOCATE(teil, text) bzw. INSTR(text, teil) (0, wenn nicht enthalten). Damit lässt sich z. B. der Teil vor einem Komma abschneiden:
SELECT LEFT('Mustermann, Max', LOCATE(',', 'Mustermann, Max') - 1) AS nachname; -- 'Mustermann'Datums- und Zeitfunktionen
| Funktion | MSSQL | MySQL/MariaDB | OracleDB | PostgreSQL | SQLite |
|---|---|---|---|---|---|
| das aktuelle Datum | CAST(GETDATE() AS date), CONVERT(date, SYSDATETIME()), ab SQL Server 2025 CURRENT_DATE |
CURDATE(), CURRENT_DATE |
TRUNC(SYSDATE) |
CURRENT_DATE |
date('now') |
| die aktuelle Zeit | CAST(SYSDATETIME() AS time), CONVERT(time, SYSDATETIME()) |
CURTIME(), Zeitpunkt: NOW() |
CURRENT_TIME, now() |
time('now','localtime') |
|
| Teil eines Datums | YEAR(d), MONTH(d), DAY(d), DATEPART(hour, d) |
YEAR(d), MONTH(d), DAY(d), HOUR(d), MINUTE(d), DAYOFWEEK(d) |
EXTRACT(YEAR FROM d) |
EXTRACT(YEAR FROM d), date_part('year', d) |
strftime('%Y', d) |
| Datums- bzw. Uhrzeitteil eines Zeitpunkts | CONVERT(date, d), CONVERT(time, d) |
DATE(d), TIME(d) |
TRUNC(d) |
d::date, d::time |
date(d), time(d) |
| Alter in vollen Jahren | DATEDIFF(year, geb, GETDATE()) zählt nur Jahreswechsel – ungenau |
TIMESTAMPDIFF(YEAR, geb, CURDATE()) |
TRUNC(MONTHS_BETWEEN(SYSDATE, geb) / 12) |
date_part('year', age(geb)) |
(CAST(strftime('%Y%m%d', 'now') AS INTEGER) - CAST(strftime('%Y%m%d', geb) AS INTEGER)) / 10000 |
| Zeitdifferenz zweier Zeitangaben in Stunden | DATEDIFF(hour, start, end) |
TIMESTAMPDIFF(HOUR, start, end) |
SELECT CAST ((julianday(end) - julianday(start)) * 24 AS INTEGER) |
||
| Zeitdifferenz zweier Datumsangaben in Tagen | DATEDIFF(day, start, end) |
TIMESTAMPDIFF(DAY, start, end), DATEDIFF(end, start) |
end - start |
end - start |
SELECT CAST ((julianday(end) - julianday(start)) AS INTEGER) |
| Zeitdifferenz zweier Zeitpunkte in Minuten (z. B. Verspätung) | DATEDIFF(minute, start, end) |
TIMESTAMPDIFF(MINUTE, start, end) |
(end - start) * 24 * 60 |
EXTRACT(EPOCH FROM end - start) / 60 |
SELECT CAST ((julianday(end) - julianday(start)) * 1440 AS INTEGER) |
| Datum verschieben | DATEADD(day, 14, d) |
d + INTERVAL 14 DAY, DATE_ADD(d, INTERVAL 14 DAY) |
d + 14 |
d + INTERVAL '14 days' |
date(d, '+14 days') |
| Datum/Zeit formatiert ausgeben | CAST(exp AS data_type[(length)]), FORMAT |
DATE_FORMAT(d, '%d.%m.%Y %H:%i'), TIME_FORMAT |
TO_CHAR(d, 'DD.MM.YYYY') |
to_char(d, 'DD.MM.YYYY') |
SELECT strftime('%Y-%m-%d', datum) |
| Dokumentation / Übersicht Datumsfunktionen (Link) | MS Doc | MySQL Doc | SQLite Doc |
Beispiele (heute sei der 18.10.2026):
SELECT vorname,
TIMESTAMPDIFF(YEAR, geburtsdatum, CURDATE()) AS alter_jahre, -- volle Jahre
YEAR(CURDATE()) - YEAR(geburtsdatum) AS zu_grob, -- ignoriert den Geburtstag im Jahr
DATE_FORMAT(geburtsdatum, '%d.%m.%Y') AS geboren
FROM benutzer;YEAR(CURDATE()) - YEAR(geburtsdatum) ist für alle, die in diesem Jahr noch nicht Geburtstag hatten, um ein Jahr zu groß. Wochentags- und Monatsnamen gibt DATE_FORMAT (%W, %M) auf Deutsch aus, wenn vorher SET lc_time_names = 'de_DE'; ausgeführt wurde.
Für den Wochentag als Zahl gibt es in MariaDB zwei Funktionen mit unterschiedlicher Zählung: WEEKDAY(d) liefert 0 (Montag) bis 6 (Sonntag), DAYOFWEEK(d) liefert 1 (Sonntag) bis 7 (Samstag); den Namen des Wochentags liefert DAYNAME(d). In SQL Server heißen die Gegenstücke DATEPART(weekday, d) und DATENAME(weekday, d) – welche Zahl der Montag hat, hängt dort von der Einstellung DATEFIRST ab. Maßgeblich ist immer die Beschreibung der Funktion in der Syntaxübersicht; ist nur „der Wochentag“ verlangt, ist eine Funktion, die den Namen liefert, am besten lesbar.
Funktionen auf einer Spalte in WHERE (z. B. WHERE YEAR(bestellt_am) = 2026) sind gut lesbar, verhindern aber die Nutzung eines Index auf dieser Spalte. Bei großen Tabellen ist ein Bereichsvergleich schneller: WHERE bestellt_am >= '2026-01-01' AND bestellt_am < '2027-01-01'.
Ablaufsteuerungsfunktionen
Fallunterscheidungen mit CASE WHEN … END und IF() sowie Ersatzwerte für NULL mit COALESCE, IFNULL und NULLIF behandelt der eigene Artikel Fallunterscheidungen und NULL (CASE, COALESCE).
Leitfragen
- Was unterscheidet skalare Funktionen von Aggregatfunktionen? Nenne je zwei Beispiele.
Skalare Funktionen (single row functions) werten nur Werte innerhalb eines Datensatzes aus und liefern je Zeile ein Ergebnis, z. B. ROUND(preis, 2) oder UPPER(name). Aggregatfunktionen (multi row functions) werten eine Spalte über viele Datensätze aus, z. B. MAX(bruttokosten) oder COUNT(*) – siehe Abschnitt „Unterschiedliche Arten von Funktionen in SQL-Statements“ und Artikel zu Aggregatfunktionen.
- Wie gibst Du von einer Rechnungsnummer
RE-2026-00412das Jahr und die laufende Nummer als Zahl aus?
Das Jahr liefert SUBSTRING('RE-2026-00412', 4, 4) (Ergebnis '2026'), die laufende Nummer z. B. RIGHT('RE-2026-00412', 5). Als Zahl erhältst Du die Teile, indem Du sie umwandelst, etwa CAST(RIGHT(rechnungsnr, 5) AS UNSIGNED) ergibt 412 – siehe Abschnitt „Zeichenkettenfunktionen“ und Abschnitt „Numerische Funktionen“.
- Wie berechnest Du das Alter einer Person in vollen Jahren, und warum ist die Differenz der Jahreszahlen ungenau?
In MariaDB berechnest Du das Alter mit TIMESTAMPDIFF(YEAR, geburtsdatum, CURDATE()). Die Differenz YEAR(CURDATE()) - YEAR(geburtsdatum) ignoriert, ob die Person in diesem Jahr schon Geburtstag hatte, und ist sonst um ein Jahr zu groß – siehe Abschnitt „Datums- und Zeitfunktionen“.
- Wie unterscheiden sich
DATEDIFFin MariaDB und in SQL Server?
In MariaDB liefert DATEDIFF(end, start) immer die Differenz in Tagen, mit dem späteren Datum zuerst; für andere Einheiten nimmst Du TIMESTAMPDIFF(einheit, start, end). In SQL Server gibst Du bei DATEDIFF(einheit, start, end) die Einheit als ersten Parameter an (z. B. day, hour, minute) und das Startdatum vor dem Enddatum; DATEDIFF(year, …) zählt dabei nur Jahreswechsel – siehe Abschnitt „Datums- und Zeitfunktionen“.
- Warum liefert
CONCAT(vorname, ' ', zweitname, ' ', nachname)bei manchen PersonenNULL, und wie verhinderst Du das?
CONCAT liefert NULL, sobald eines der Argumente NULL ist – also bei allen Personen ohne Zweitnamen. Verhindern kannst Du das mit CONCAT_WS(' ', vorname, zweitname, nachname), das NULL-Werte überspringt, oder mit einem Ersatzwert über COALESCE – siehe Abschnitt „Zeichenkettenfunktionen“ und Abschnitt „Ablaufsteuerungsfunktionen“.
- Warum kann
WHERE YEAR(datum) = 2026bei großen Tabellen langsam sein?
Eine Funktion auf einer Spalte in der WHERE-Bedingung verhindert, dass das DBMS einen Index auf dieser Spalte nutzt, sodass die ganze Tabelle durchsucht wird. Schneller ist ein Bereichsvergleich wie WHERE datum >= '2026-01-01' AND datum < '2027-01-01' – siehe Abschnitt „Datums- und Zeitfunktionen“.
Links und weitere Informationen
Selektion und Projektion, Fallunterscheidungen und NULL (CASE, COALESCE) und Aggregatfunktionen und Gruppierung
als Nachschlagewerk: MariaDB Knowledge Base: Built-in Functions
als Nachschlagewerk: MariaDB Knowledge Base: DATE_FORMAT
Hinweis zur Nachnutzung als Open Educational Resource (OER)
Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: “Funktionen im SELECT-Clause (Single-Row-Functions)” von oer-informatik.de (H. Stein), Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/sql-dml-singlerowfunctions veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/db-sql/sql. Erstellt mit KI-Assistenz; von mir umfassend redaktionell überarbeitet, geprüft und freigegeben. Stand: 28.10.2026.
[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]
