PERFORMってPostgreSQLの世界だと、無口なヒーローみたいな存在なんだ。やるべきことをサッとやって、返り値とか何も残さずに消えていく感じ。このコマンドは、PL/pgSQLの関数の中でSQLクエリを実行したいけど、結果を処理したり保存したりする必要がないときに使うよ。PERFORMの主な役割は、何かを起こすためにクエリを呼び出すこと。例えばデータの変更や、別の関数の呼び出しとかで、結果を受け取ることじゃないんだ。
PERFORMは、クエリの結果がいらないときに使うんだ。普通のSELECTは、何かしら結果を使う前提だけど、PERFORMはただクエリを実行して、何も言わずに次に進む。特に、関数を副作用(例えばログに書き込むとか)のためだけに呼び出すときに便利。こういう使い方だと、コードがシンプルで分かりやすくなるよ。余計なことが減って、意味がはっきりする。
PERFORMの使い方例
関数の呼び出し
実際の例で見てみよう。例えば、log_actionっていう関数があって、ユーザーのアクションをログに記録するものだとする。この関数は何も返さないし、ただ動いてくれればOK。PERFORMを使うとこうなるよ:
CREATE OR REPLACE FUNCTION log_action(user_id INT, action TEXT) RETURNS VOID AS $$
BEGIN
INSERT INTO logs (user_id, action, log_time)
VALUES (user_id, action, NOW());
END;
$$ LANGUAGE plpgsql;
-- そしてPERFORMでこの関数を呼び出す:
PERFORM log_action(5, 'ユーザーがログインした');
ここで何が起きてるかというと、PERFORMがlog_action関数を呼び出して、logsテーブルにレコードを追加してるんだ。ポイントは、関数の返り値は無視されるってこと。副作用のためだけに使ってるんだよ。
データの更新
たまにPERFORMは、クエリの結果に興味がないけどデータを変更したいときにも便利。例えば、ordersテーブルの注文ステータスを更新する場合:
CREATE OR REPLACE FUNCTION update_order_status(order_id INT, new_status TEXT) RETURNS VOID AS $$
BEGIN
UPDATE orders
SET status = new_status
WHERE id = order_id;
END;
$$ LANGUAGE plpgsql;
-- この関数をPERFORMで呼び出す:
PERFORM update_order_status(101, '発送済み');
ここではupdate_order_statusが注文ID101のステータスを更新してる。関数内のSQLクエリの結果は気にしないから、PERFORMがぴったりなんだ。
補助的な操作の実行
関数の中には、複雑な処理をサポートするための「補助的」なロジックが入ってることもあるよね。例えば、テーブルを更新した後にキャッシュをクリアしたい場合:
CREATE OR REPLACE FUNCTION clear_cache() RETURNS VOID AS $$
BEGIN
DELETE FROM cache_table;
END;
$$ LANGUAGE plpgsql;
-- 別の関数の中で呼び出す:
CREATE OR REPLACE FUNCTION update_product(product_id INT, new_price NUMERIC) RETURNS VOID AS $$
BEGIN
UPDATE products
SET price = new_price
WHERE id = product_id;
-- データ変更後にキャッシュをクリア:
PERFORM clear_cache();
END;
$$ LANGUAGE plpgsql;
これが魔法みたいなところで、PERFORMを使えば、結果がいらない関数をどんどん呼び出して処理を進められるんだ。
実践課題
PERFORMが開発者の生活をどれだけ楽にしてくれるか、いくつか例を見てみよう。
例1: 手順の各ステージのログ記録
例えば、複雑な支払い処理の手順があって、その各ステージをログに記録したいとする。情報を書き込むlog_stage関数を作って、PERFORMで使う:
CREATE OR REPLACE FUNCTION log_stage(stage_name TEXT) RETURNS VOID AS $$
BEGIN
INSERT INTO process_logs(stage, log_time)
VALUES (stage_name, NOW());
END;
$$ LANGUAGE plpgsql;
-- こんな感じの手順:
CREATE OR REPLACE FUNCTION process_payment(payment_id INT) RETURNS VOID AS $$
BEGIN
-- 開始をログ
PERFORM log_stage('支払い処理開始');
-- 最初のステージ
UPDATE payments
SET status = '処理中'
WHERE id = payment_id;
PERFORM log_stage('支払いステータス更新');
-- 最終ステージ
UPDATE payments
SET status = '完了'
WHERE id = payment_id;
PERFORM log_stage('支払い完了');
END;
$$ LANGUAGE plpgsql;
ここではlog_stageをPERFORMで呼び出して、各ステージごとに実行状態を記録してる。これでデバッグもしやすくなるよ。
例2: 通知のアクティベート
通知システムがあって、重要なアクションごとに通知を送りたいとする。PERFORMで通知用関数を呼び出せる:
CREATE OR REPLACE FUNCTION send_notification(user_id INT, message TEXT) RETURNS VOID AS $$
BEGIN
INSERT INTO notifications (user_id, message, created_at)
VALUES (user_id, message, NOW());
END;
$$ LANGUAGE plpgsql;
-- 手順の中で使う:
CREATE OR REPLACE FUNCTION complete_task(task_id INT) RETURNS VOID AS $$
DECLARE
user_id INT;
BEGIN
-- タスクの担当者を取得
SELECT assigned_to INTO user_id
FROM tasks
WHERE id = task_id;
-- タスクを完了
UPDATE tasks
SET status = '完了'
WHERE id = task_id;
-- 通知を送信
PERFORM send_notification(user_id, 'あなたのタスクが完了しました');
END;
$$ LANGUAGE plpgsql;
ここでもPERFORMは副作用(通知送信)だけに集中して、関数の返り値は無視してる。
便利なヒントとよくあるミス
PERFORMを使うときは、いくつか注意点があるよ。例えば、PERFORMはクエリがデータを返したかどうかをチェックしない。つまり、関数やSQLクエリの結果がロジック的に重要な場合は、SELECT INTOを使った方がいい。例を見てみよう:
-- 潜在的なミス
PERFORM some_function_that_must_return_value();
-- 修正例
SELECT some_function_that_must_return_value() INTO some_variable;
もう一つよくあるミスは、PERFORMを使うべきじゃない場面、つまりクエリの結果が必要なときに使っちゃうこと。そういうときは、ちゃんと結果を受け取ってチェックしよう。
実際のプロジェクトでは、PERFORMを使うことで関数や手順がシンプルで読みやすく、デバッグもしやすくなる。ログ記録(RAISE NOTICE)や、PostgreSQLの組み込み診断関数(current_query()など)と組み合わせると、信頼性が高くて管理しやすいシステム作りに役立つよ。
GO TO FULL VERSION