画像ツール一覧

ストアドプロシージャ

Stored Procedure

データベース

複数のSQL文で構成される複雑な処理手順を、あらかじめデータベース側に保存しておき、1つのコマンドで呼び出せるようにしたプログラムのこと。

🐾 猫で例えると?

お正月の鏡餅の飾りを頭に乗せられ、少し不満そうにしながらもじっと耐えている茶トラ猫
呼び出すだけで実行される「一連のお決まりの処理」

頭に鏡餅の飾りを乗せた茶トラ。「飾りを用意する」→「頭に乗せる」→「写真を撮る」という一連の手順を考えます。これを毎回イチから指示するのではなく、「猫かぶり処理」として事前に登録しておくことで、一発で実行できるようにした状態がストアドプロシージャです。

🐾 PR

💻 データベース開発における「ストアドプロシージャ」とは?

アプリケーションを開発する際、データベースに対して「データを検索して、計算して、別のテーブルを更新して…」といった複数のSQLを順番に実行したい場面が多々あります。通常はアプリケーション側からSQLを1つずつ発行しますが、これだとネットワーク通信の回数が増え、処理が遅くなる原因となります。

複数のSQLをDB側でまとめて実行すると、アプリとDBの往復を減らせる場合があります。ただし、処理内容や実行計画によって性能は変わり、ストアドプロシージャにするだけで必ず速くなるわけではありません。

⚠️ ストアドプロシージャの仕組みと注意点

実行権限を整理し、DB操作の入口を限定する用途にも使えます。ただし、内部で入力を連結した動的SQLを作ればSQLインジェクションの危険は残ります。パラメータの適切な利用と、必要最小限の権限が重要です。

ブラックボックス化の罠

次はMySQLの例です。usersとpoint_historyが存在し、対象の利用者IDが有効であることを前提とします。DELIMITERはmysqlクライアントの区切り設定で、サーバーへ送るSQL文ではありません。プロシージャはCALLで呼び出し、行の更新を契機に動くトリガーとは区別します。

-- MySQLでのストアドプロシージャの作成例
DELIMITER //

CREATE PROCEDURE UpdateUserPoints(IN userId INT, IN addPoints INT)
BEGIN
    -- 1. ユーザーのポイントを更新
    UPDATE users SET points = points + addPoints WHERE id = userId;
    
    -- 2. ポイント履歴テーブルにログを追加
    INSERT INTO point_history (user_id, added_points, created_at) 
    VALUES (userId, addPoints, NOW());
END //

DELIMITER ;

-- アプリケーション側からの呼び出し(これ1行で済む)
CALL UpdateUserPoints(101, 500);

この例は2つのSQLをまとめていますが、BEGINとENDは処理のまとまりを表し、それだけでトランザクションにはなりません。両方を一体として確定するには、トランザクション対応テーブルを使い、呼び出し側などで開始・確定・エラー時のロールバックを設計します。

🛠️ ストアドプロシージャを賢く使うためのポイント

現場でストアドプロシージャを導入する際は、運用面でのルール決めが不可欠です。

猫との決まった手順のように、繰り返すDB操作をまとめるのがストアドプロシージャです。性能、権限、テストのしやすさを確かめながら、アプリ側に置く処理との境界を決めましょう。