アプリケーションからデータベースに処理を渡す際、ビジネスロジックの一部をデータベース内に組み込むことができれば、パフォーマンスの向上や再利用性の確保につながります。
本章では、ユーザー定義関数(UDF)、ストアドプロシージャ、例外処理を実践例とともに解説します。
ユーザー定義関数(UDF)の書き方
UDF(User Defined Function)とは、SQLで独自の処理を関数として定義できる機能です。計算ロジックやデータ整形処理など、共通化したい処理を一箇所にまとめておくことができます。
PostgreSQLでのUDF例(PL/pgSQL)
CREATE FUNCTION calc_tax(price NUMERIC) RETURNS NUMERIC AS $$ BEGIN RETURN price * 0.1; END; $$ LANGUAGE plpgsql;
呼び出し方:
SELECT calc_tax(1000); -- → 100.0
MySQLでのUDF例
DELIMITER $$ CREATE FUNCTION calc_tax(price DECIMAL(10,2)) RETURNS DECIMAL(10,2) DETERMINISTIC BEGIN RETURN price * 0.1; END$$ DELIMITER ;
ポイント: UDFは SELECT 文の中で呼び出せる点が特徴で、ビューやクエリの中での再利用性が高くなります。
ストアドプロシージャと引数・戻り値
ストアドプロシージャ(Stored Procedure)は、複数のSQL文をまとめた「処理のかたまり」です。UDFと異なり、CALL 文で実行し、主に更新系処理に利用されます。
PostgreSQLでの例
CREATE PROCEDURE transfer_funds(sender_id INT, receiver_id INT, amount NUMERIC) LANGUAGE plpgsql AS $$ BEGIN UPDATE accounts SET balance = balance - amount WHERE id = sender_id; UPDATE accounts SET balance = balance + amount WHERE id = receiver_id; END; $$;
実行方法:
CALL transfer_funds(1, 2, 1000);
MySQLでの例(IN/OUTパラメータ)
DELIMITER $$ CREATE PROCEDURE get_user_email(IN user_id INT, OUT email VARCHAR(100)) BEGIN SELECT u.email INTO email FROM users u WHERE u.id = user_id; END$$ DELIMITER ;
呼び出し例(MySQL CLI):
CALL get_user_email(1, @email); SELECT @email;
関数 vs プロシージャの違い
| 項目 | 関数(UDF) | ストアドプロシージャ |
|---|---|---|
| 呼び出し方法 | SELECT文の中 | CALL文 |
| 主な用途 | 計算・データ取得 | データ更新・複数処理 |
| 戻り値 | RETURNで単一値 | OUTパラメータで複数可 |
例外処理(TRY…CATCH)
データベース処理中にエラーが発生した場合、トランザクションをロールバックしたり、ログを記録するなどの例外処理が必要になります。
PostgreSQLの例外処理(EXCEPTION)
CREATE PROCEDURE safe_transfer(sender_id INT, receiver_id INT, amount NUMERIC) LANGUAGE plpgsql AS $$ BEGIN BEGIN UPDATE accounts SET balance = balance - amount WHERE id = sender_id; UPDATE accounts SET balance = balance + amount WHERE id = receiver_id; EXCEPTION WHEN OTHERS THEN RAISE NOTICE 'エラー発生:送金失敗'; ROLLBACK; END; END; $$;
MySQLでの例外処理(DECLARE CONTINUE HANDLER)
DELIMITER $$ CREATE PROCEDURE safe_insert() BEGIN DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN SELECT 'エラー発生:処理中断'; END; START TRANSACTION; INSERT INTO users(name) VALUES('山田太郎'); -- 故意にエラーを起こす INSERT INTO users(id) VALUES('invalid'); COMMIT; END$$ DELIMITER ;
このように例外処理を入れることで、システム全体の安定性を高めることができます。
まとめ
関数とストアドプロシージャを活用することで、SQLロジックを再利用可能な形でデータベースに集約できます。
- UDFで共通の計算・処理をシンプルに
- ストアドプロシージャで複雑な処理を1つにまとめ、再利用
- 例外処理で障害に強いデータベースロジックを構築
特に複雑な業務ロジックを抱えるシステムでは、これらを使いこなすことで保守性とパフォーマンスが大きく向上します。

