MySQL-Funktionen sind ähnlich wie Stored Procedures, mit dem Hauptunterschied, dass sie einen Wert zurückgeben müssen. Sie können in SQL-Anweisungen wie normale MySQL-Funktionen verwendet werden.
DELIMITER //
CREATE FUNCTION rabatt_berechnen(
p_preis DECIMAL(10,2),
p_kundentyp CHAR(1)
)
RETURNS DECIMAL(10,2)
DETERMINISTIC
BEGIN
DECLARE v_rabatt DECIMAL(10,2);
CASE p_kundentyp
WHEN 'A' THEN SET v_rabatt = p_preis * 0.1;
WHEN 'B' THEN SET v_rabatt = p_preis * 0.05;
ELSE SET v_rabatt = 0;
END CASE;
RETURN v_rabatt;
END //
DELIMITER ;
-- Verwendung in einer Abfrage
SELECT
produkt_id,
preis,
kundentyp,
rabatt_berechnen(preis, kundentyp) AS rabatt
FROM produkte
JOIN kunden USING (kunde_id);-- Deterministische Funktion (gleiche Eingabe = gleiche Ausgabe)
CREATE FUNCTION mwst_berechnen(
p_nettobetrag DECIMAL(10,2)
)
RETURNS DECIMAL(10,2)
DETERMINISTIC
BEGIN
RETURN p_nettobetrag * 0.19;
END;
-- Nicht-deterministische Funktion
CREATE FUNCTION zufallspreis(
p_min DECIMAL(10,2),
p_max DECIMAL(10,2)
)
RETURNS DECIMAL(10,2)
NOT DETERMINISTIC
BEGIN
RETURN p_min + RAND() * (p_max - p_min);
END;DELIMITER //
CREATE FUNCTION kundenrabatt_berechnen(
p_kunden_id INT
)
RETURNS DECIMAL(5,2)
READS SQL DATA
BEGIN
DECLARE v_umsatz DECIMAL(10,2);
DECLARE v_kundentyp CHAR(1);
DECLARE v_rabatt DECIMAL(5,2);
-- Gesamtumsatz des Kunden ermitteln
SELECT SUM(betrag)
INTO v_umsatz
FROM bestellungen
WHERE kunde_id = p_kunden_id
AND datum >= DATE_SUB(CURRENT_DATE, INTERVAL 1 YEAR);
-- Kundentyp ermitteln
SELECT kundentyp
INTO v_kundentyp
FROM kunden
WHERE kunde_id = p_kunden_id;
-- Rabatt basierend auf Umsatz und Kundentyp
SET v_rabatt = CASE
WHEN v_kundentyp = 'A' AND v_umsatz >= 10000 THEN 15
WHEN v_kundentyp = 'A' AND v_umsatz >= 5000 THEN 10
WHEN v_kundentyp = 'B' AND v_umsatz >= 10000 THEN 10
WHEN v_kundentyp = 'B' AND v_umsatz >= 5000 THEN 5
ELSE 0
END;
RETURN v_rabatt;
END //
DELIMITER ;DELIMITER //
CREATE FUNCTION lagerbestand_pruefen(
p_produkt_id INT
)
RETURNS VARCHAR(20)
READS SQL DATA
BEGIN
DECLARE v_bestand INT;
DECLARE v_min_bestand INT;
-- Aktuellen und minimalen Bestand ermitteln
SELECT lagerbestand, mindestbestand
INTO v_bestand, v_min_bestand
FROM produkte
WHERE produkt_id = p_produkt_id;
-- Status zurückgeben
RETURN CASE
WHEN v_bestand IS NULL THEN 'Unbekannt'
WHEN v_bestand = 0 THEN 'Nicht verfügbar'
WHEN v_bestand < v_min_bestand THEN 'Nachbestellen'
ELSE 'Verfügbar'
END;
END //
DELIMITER ;
-- Verwendung in einer Abfrage
SELECT
produkt_id,
bezeichnung,
lagerbestand,
lagerbestand_pruefen(produkt_id) AS status
FROM produkte;DELIMITER //
CREATE FUNCTION arbeitstage_berechnen(
p_start_datum DATE,
p_end_datum DATE
)
RETURNS INT
DETERMINISTIC
BEGIN
DECLARE v_tage INT;
DECLARE v_arbeitstage INT;
DECLARE v_datum DATE;
SET v_tage = DATEDIFF(p_end_datum, p_start_datum);
SET v_arbeitstage = 0;
SET v_datum = p_start_datum;
WHILE v_datum <= p_end_datum DO
-- Wenn kein Wochenende
IF DAYOFWEEK(v_datum) NOT IN (1, 7) THEN
SET v_arbeitstage = v_arbeitstage + 1;
END IF;
SET v_datum = DATE_ADD(v_datum, INTERVAL 1 DAY);
END WHILE;
RETURN v_arbeitstage;
END //
DELIMITER ;DELIMITER //
CREATE FUNCTION formatiere_telefon(
p_telefon VARCHAR(20)
)
RETURNS VARCHAR(20)
DETERMINISTIC
BEGIN
DECLARE v_nummer VARCHAR(20);
-- Nur Zahlen behalten
SET v_nummer = REGEXP_REPLACE(p_telefon, '[^0-9]', '');
-- Format: +49 (xxx) xxx-xxxx
IF LENGTH(v_nummer) = 11 AND LEFT(v_nummer, 2) = '49' THEN
RETURN CONCAT('+',
LEFT(v_nummer, 2), ' ',
'(', SUBSTRING(v_nummer, 3, 3), ') ',
SUBSTRING(v_nummer, 6, 3), '-',
RIGHT(v_nummer, 4)
);
ELSE
RETURN p_telefon;
END IF;
END //
DELIMITER ;Praktische Tipps:
-- Häufig verwendete Werte in Variable speichern
CREATE FUNCTION berechne_zwischensumme(
p_bestell_id INT
)
RETURNS DECIMAL(10,2)
READS SQL DATA
BEGIN
DECLARE v_summe DECIMAL(10,2);
SELECT SUM(menge * einzelpreis)
INTO v_summe
FROM bestellpositionen
WHERE bestell_id = p_bestell_id;
RETURN COALESCE(v_summe, 0);
END;CREATE FUNCTION sichere_division(
p_zahl1 DECIMAL(10,2),
p_zahl2 DECIMAL(10,2)
)
RETURNS DECIMAL(10,2)
DETERMINISTIC
BEGIN
IF p_zahl2 = 0 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Division durch Null!';
END IF;
RETURN p_zahl1 / p_zahl2;
END;-- Generische Funktion für verschiedene Anwendungsfälle
CREATE FUNCTION format_waehrung(
p_betrag DECIMAL(10,2),
p_waehrung CHAR(3)
)
RETURNS VARCHAR(20)
DETERMINISTIC
BEGIN
RETURN CASE p_waehrung
WHEN 'EUR' THEN CONCAT(FORMAT(p_betrag, 2), ' €')
WHEN 'USD' THEN CONCAT('$', FORMAT(p_betrag, 2))
WHEN 'GBP' THEN CONCAT('£', FORMAT(p_betrag, 2))
ELSE FORMAT(p_betrag, 2)
END;
END;