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 ROUND runden.

  • … Zeichenketten mit LEFT, RIGHT, SUBSTRING, CONCAT, CHAR_LENGTH, UPPER/LOWER und TRIM bearbeiten, z. B. Nummern zerlegen oder Namen abkürzen.

  • … mit CURDATE(), YEAR(), MONTH(), HOUR(), DATEDIFF und TIMESTAMPDIFF Datumsteile, Differenzen und das Alter berechnen und mit DATE_FORMAT formatieren.

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?

Deterministische und nicht deterministische Funktionen
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 und skalare Funktionen
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 (UPPER, ROUND) liefern je Artikel eine Zeile, Aggregatfunktionen (MAX, COUNT) eine einzige Zeile für alle Artikel (mit KI erstellt)

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

Numerische Funktionen in verschiedenen DBMS
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

Zeichenkettenfunktionen in verschiedenen DBMS
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

Datums- und Zeitfunktionen in verschiedenen DBMS
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

  1. 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.

  1. Wie gibst Du von einer Rechnungsnummer RE-2026-00412 das 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“.

  1. 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“.

  1. Wie unterscheiden sich DATEDIFF in 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“.

  1. Warum liefert CONCAT(vorname, ' ', zweitname, ' ', nachname) bei manchen Personen NULL, 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“.

  1. Warum kann WHERE YEAR(datum) = 2026 bei 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“.


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]

Kommentare gerne per Mastodon, Verbesserungsvorschläge per gitlab issue (siehe oben). Beitrag teilen: