CodeGym /コース /SQL SELF /エラーロギング:ロギングレベルとメッセージのフォーマット

エラーロギング:ロギングレベルとメッセージのフォーマット

SQL SELF
レベル 55 , レッスン 2
使用可能

今、俺たちはまるでシークレットエージェントみたいなもんだよね ― 関数やプロシージャがミッションをこなしてる。データを処理したり、計算したり、データベースの中でちょっとしたマジックをやってる。でも、もし何かうまくいかなかったらどうやって気づく?どのタイミングで「データのマッサージバス」が壊れたか、どうやって分かる?そこで登場するのがロギングとエラー処理だよ。

覚えてる?もうPostgreSQLやPL/pgSQLでどうやって「会話」したりログを取ったりできるか、ちょっと触れたよね:

  • RAISE NOTICE: 落ち着いたフレンドリーなトーン ― 「おい、ここは大丈夫だけど、ちょっと見てみてもいいかもよ」。
  • RAISE WARNING: ちょっと声が大きくなる ― 「あれ、なんか変かも。ちょっと覗いてみて」。
  • RAISE EXCEPTION: パニックサイレン ― 「ストップ!アルゴリズムがピンチ!全部ぶっ壊れる前に止めたよ」。

それぞれのレベルにはちゃんと役割があるから、どれを使うかちゃんと選ぶのが大事だよ。

コードの中でこうやって使う:

DO $$
BEGIN
    -- NOTICEレベル(全部OK、ただのお知らせ)
    RAISE NOTICE 'ただのお知らせ:データ処理が始まったよ';

    -- WARNINGレベル(なんか怪しい)
    RAISE WARNING '警告:カラムのデータフォーマットが正しくないかも';

    -- EXCEPTIONレベル(クリティカルエラー)
    RAISE EXCEPTION 'エラー:入力値が不正だよ!';
END $$;

使い分けのタイミング:

  • RAISE NOTICE ― デバッグや落ち着いた情報出力用。
  • RAISE WARNING ― データが怪しい時の警告用。
  • RAISE EXCEPTION ― クリティカルなエラーで関数の実行を止めたい時。

RAISE EXCEPTIONでのエラー処理

RAISE EXCEPTIONは君の非常停止ボタン。何かおかしい時に関数の実行を止めてエラーを伝えられる。

基本の使い方はこんな感じ:

RAISE EXCEPTION 'エラーメッセージをここに書く';

でも、もっと分かりやすくしたいなら変数も使える:

DECLARE
    input_value INTEGER;
BEGIN
    input_value := NULL;

    IF input_value IS NULL THEN
        RAISE EXCEPTION 'エラー:入力値がNULLだよ。INTEGERが欲しかった';
    END IF;
END;

メッセージのフォーマット

変数をメッセージの中に直接入れることもできる:

DECLARE
    var1 TEXT := 'データ';
    var2 INTEGER := 42;
BEGIN
    RAISE EXCEPTION '処理中にエラー:%、ID %', var1, var2;
END;

出力例:処理中にエラー:データ、ID 42

例:データのバリデーション

例えば、年齢を受け取るプロシージャがあるとする。年齢がマイナスなら、エラーを出すのが普通だよね:

CREATE OR REPLACE FUNCTION validate_age(age INTEGER)
RETURNS VOID AS $$
BEGIN
    IF age < 0 THEN
        RAISE EXCEPTION '年齢はマイナスにできないよ:%', age;
    END IF;
END;
$$ LANGUAGE plpgsql;

-- 関数の呼び出し
SELECT validate_age(-5);  -- エラーになる

RAISE NOTICEでのお知らせ

RAISE EXCEPTIONがサイレンなら、RAISE NOTICEは肩をポンと叩く感じ。関数の中で何が起きてるかコメントを入れるのに使える。

RAISE NOTICEを使うタイミング:

  • デバッグ情報の出力(例えば変数の今の値とか)。
  • 処理のステップ開始や計算結果のお知らせ。

例:インフォメーションメッセージ

CREATE OR REPLACE FUNCTION calculate_discount(price NUMERIC, discount_rate NUMERIC)
RETURNS NUMERIC AS $$
DECLARE
    final_price NUMERIC;
BEGIN
    RAISE NOTICE '割引前の価格:%', price;
    RAISE NOTICE '割引率:%', discount_rate;

    final_price := price - (price * discount_rate);

    RAISE NOTICE '最終価格:%', final_price;

    RETURN final_price;
END;
$$ LANGUAGE plpgsql;

-- 関数の呼び出し
SELECT calculate_discount(100, 0.2);
-- 出力例:
-- NOTICE: 割引前の価格:100
-- NOTICE: 割引率:0.2
-- NOTICE: 最終価格:80

実践例:計画とロギング

例えば、複雑なデータ処理プロシージャがあって、今どのステップか知りたいとき:

CREATE OR REPLACE FUNCTION process_data_step_by_step()
RETURNS VOID AS $$
BEGIN
    RAISE NOTICE 'ステップ1:データ準備';
    -- ここに最初のステップのロジック

    RAISE NOTICE 'ステップ2:データバリデーション';
    -- ここに2番目のステップのロジック

    RAISE NOTICE 'ステップ3:データ保存';
    -- ここに3番目のステップのロジック
END;
$$ LANGUAGE plpgsql;

-- 関数の呼び出し
SELECT process_data_step_by_step();
-- ログにステップごとの実行が表示される

もう一つ例を出すね。 例えば、あるショップが一定金額以上の注文だけ割引を提供する場合:

CREATE OR REPLACE FUNCTION apply_discount(order_amount NUMERIC)
RETURNS NUMERIC AS $$
BEGIN
    IF order_amount < 50 THEN
        RAISE EXCEPTION 'エラー:注文金額は50以上じゃないとダメ、今の金額:%', order_amount;
    END IF;

    RETURN order_amount * 0.9;  -- 10%割引を適用
END;
$$ LANGUAGE plpgsql;

-- 関数の呼び出し
SELECT apply_discount(30);  -- エラー:注文金額は50以上じゃないとダメ

よくあるミス

ミス1: パラメータなしでメッセージをロギングする。

大きなプロシージャだと、これじゃ何が起きたか分かりにくい:

RAISE NOTICE 'エラーが発生した';  -- なんで?どこで?どうやって?

アドバイス: いつもコンテキストを追加しよう:

RAISE NOTICE 'process_data()関数でエラー:入力値:%', input_value;

ミス2: RAISE EXCEPTIONRAISE WARNINGで十分な場面で使っちゃう。

例外を乱用すると、ちょっとしたことでコードが止まってデータ処理が大変になるよ。

コツ: ロギングレベルは意識して使い分けよう。デバッグにはNOTICE、クリティカルな時はEXCEPTION

ミス3: ロギング自体を全くしない。

これは暗い部屋で鍵を探すようなもん。ログがないと複雑な処理のデバッグはほぼ無理ゲー。

コツ: 関数が大きくて複雑な時は特に、重要なステップでRAISE NOTICEを入れよう。

コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION