DELIMITER $$
CREATE PROCEDURE имя_процедуры (
IN параметр1 ТИП,
IN параметр2 ТИП,
...
)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
RESIGNAL;
END;
START TRANSACTION;
-- Проверки, вставки, обновления
COMMIT;
END$$
DELIMITER ;
DELIMITER $$
CREATE PROCEDURE оформить_продажу(
IN p_id_dog INT,
IN p_id_cli INT,
IN p_cost DECIMAL(10,2)
)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
RESIGNAL;
END;
START TRANSACTION;
IF NOT EXISTS (SELECT 1 FROM dog WHERE id_dog = p_id_dog) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Питомец не найден';
END IF;
IF NOT EXISTS (SELECT 1 FROM clients WHERE id_cli = p_id_cli) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Клиент не найден';
END IF;
INSERT INTO orders (date_ord, status_order, cost, id_dog, id_cli)
VALUES (CURDATE(), 'в пути', p_cost, p_id_dog, p_id_cli);
COMMIT;
END$$
DELIMITER ;
Пример:
CALL оформить_продажу(2, 1, 3000.00);
p_id_dog = 2
: ID питомцаp_id_cli = 1
: ID клиентаp_cost = 3000.00
: Стоимость заказаОткатывает транзакцию при ошибке. Используйте:
ROLLBACK; RESIGNAL;
Гарантирует атомарность — либо всё выполняется, либо ничего:
START TRANSACTION;
INSERT INTO orders (...) VALUES (...);
UPDATE dog SET status = 'продан' WHERE id_dog = ...;
COMMIT;
Проверяет существование данных:
IF NOT EXISTS (SELECT 1 FROM dog WHERE id_dog = p_id_dog) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Питомец не найден';
END IF;
Выбрасывает пользовательское исключение:
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Питомец не найден';
Устанавливает текущую дату:
VALUES (CURDATE(), 'в пути', p_cost, p_id_dog, p_id_cli);
Ошибка | Причина | Решение |
---|---|---|
Error 1452 |
id_dog или id_cli отсутствует | Проверьте существование питомца и клиента |
Error 1062 |
Дублирование id_ord | Используйте автоинкремент для id_ord |
Error 1338 |
Некорректный синтаксис | Проверьте DELIMITER $$ и закрытие END$$ |
CALL оформить_продажу(2, 1, 3000.00);
Проверьте таблицу orders: должен появиться новый заказ.
CALL оформить_продажу(999, 1, 3000.00);
Должна вылететь ошибка: "Питомец не найден".
CALL оформить_продажу(2, 999, 3000.00);
Должна вылететь ошибка: "Клиент не найден".
DELIMITER $$
CREATE PROCEDURE имя_процедуры (
IN параметр1 ТИП,
IN параметр2 ТИП,
...
)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
RESIGNAL;
END;
START TRANSACTION;
IF NOT EXISTS (SELECT 1 FROM таблица WHERE условие) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Ошибка';
END IF;
INSERT INTO orders (...) VALUES (...);
COMMIT;
END$$
DELIMITER ;