← К оглавлению занятия

💻 Примеры

📁 Блок: SQL / MySQL / Пользовательские функции ⏱️ Время изучения: ~90 мин 🎯 Сложность: Продвинутая

⚡ Кратко: 💻 примеры

Пользовательская функция в MySQL создаётся командой CREATE FUNCTION и возвращает одно значение.

Функция объявляет параметры, тип результата через RETURNS, тело между BEGIN и END, а результат отдаёт через RETURN.

Для MySQL в учебных примерах используется DELIMITER //, чтобы точки с запятой внутри тела не завершали весь скрипт раньше времени.

Ключевое свойство DETERMINISTIC означает, что при одинаковых входных данных функция возвращает одинаковый результат.

Минимальный пример: SELECT square_root(25); после создания функции square_root(x DOUBLE) вернёт квадратный корень.

Топ-3 ошибки: забыть DELIMITER, не указать RETURNS, использовать функцию с текущей датой как DETERMINISTIC без проверки документации.

Пример 1. Квадратный корень

DELIMITER //

CREATE FUNCTION square_root(x DOUBLE)
RETURNS DOUBLE
DETERMINISTIC
BEGIN
    RETURN SQRT(x);
END //

DELIMITER ;

SELECT square_root(25);

Функция принимает число x, передаёт его во встроенную SQRT и возвращает результат. Вызов через SELECT нужен, потому что функция отдаёт значение, а не выполняет процесс.

Пример 2. Возраст по дате рождения

DELIMITER //

CREATE FUNCTION calculate_age(birthdate DATE)
RETURNS INT
DETERMINISTIC
BEGIN
    RETURN TIMESTAMPDIFF(YEAR, birthdate, CURDATE());
END //

DELIMITER ;

SELECT calculate_age('1990-01-01');

TIMESTAMPDIFF(YEAR, birthdate, CURDATE()) считает разницу в полных годах между датой рождения и текущей датой.

Проверить по документации

Так как CURDATE() зависит от текущей даты, характеристику такой функции в реальном проекте нужно сверить с правилами MySQL для stored functions и binary logging.

Пример 3. Приветствие

DELIMITER //

CREATE FUNCTION greet_user(name VARCHAR(100))
RETURNS VARCHAR(255)
DETERMINISTIC
BEGIN
    RETURN CONCAT('Hello, ', name, '!');
END //

DELIMITER ;

SELECT greet_user('Alice');

CONCAT склеивает строковые части. Размер VARCHAR(255) для результата выбран с запасом относительно имени.