CodeGym /コース /SQL SELF /データ挿入・更新時のエラー処理

データ挿入・更新時のエラー処理

SQL SELF
レベル 22 , レッスン 3
使用可能

新しいデータをテーブルに挿入するときによくあるエラーを見ていこう。

エラー1: 必須フィールドにNULLを入れようとした

PostgreSQLはデータベースのルールをちゃんと守るようにしてるんだ。エラーの原因になる制約の例を見てみよう:

CREATE TABLE students (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL, -- 名前はNULLにできない
    age INT
);

-- エラー: nameフィールドは必須だよ
INSERT INTO students (name, age) VALUES (NULL, 20);

結果: エラー null value in column "name" of relation "students" violates not-null constraint`

どんなデータを追加してるかちゃんと気をつけてね。このカラムは前はNULLを許してたかもしれないけど、今は必須項目だよ。

エラー2: ユニークなカラムでデータが重複した

CREATE TABLE courses (
    course_id SERIAL PRIMARY KEY,
    course_name TEXT UNIQUE -- コース名はユニークじゃなきゃダメ
);

-- 最初の挿入はOK
INSERT INTO courses (course_name) VALUES ('SQL Basics');

-- 2回目の挿入でエラー
INSERT INTO courses (course_name) VALUES ('SQL Basics');

結果: エラー duplicate key value violates unique constraint`

たいていこれは自分のミスじゃなくて、ユーザーがうっかり同じ操作をもう一度やっちゃっただけ。こういうときは特に何もしなくて大丈夫。

エラー3: 外部キー制約違反

CREATE TABLE enrollments (
    enrollment_id SERIAL PRIMARY KEY,
    student_id INT REFERENCES students(id), -- このIDの学生が存在しなきゃダメ
    course_id INT REFERENCES courses(course_id)
);

-- エラー: ID=99の学生はいない
INSERT INTO enrollments (student_id, course_id) VALUES (99, 1);

結果: エラー insert or update on table "enrollments" violates foreign key constraint`

こういうエラーが出るのはむしろ良いこと。データベースの整合性が壊れるよりマシだよ。たぶんDBを操作するコードにバグがあるか、データが古くなってる。どっちにしても、DBが整合性を守ってくれるのはありがたい。

PostgreSQLでのエラー処理

うん、エラーは起きるもの。でも大事なのは、気づくだけじゃなくてちゃんと対処できることだよ。

トランザクションでデータを守る

データを扱うときは、よくトランザクションを使ってデータの一貫性を保つよ。エラーが起きたら変更を元に戻せる。

例:2つのテーブルにデータを追加する場合。

BEGIN; -- トランザクション開始

-- studentsテーブルにデータを挿入
INSERT INTO students (name, age) VALUES ('Otto Lin', 21);

-- enrollmentsテーブルにレコードを挿入
-- ここでID=10のコースがなければエラーになる
INSERT INTO enrollments (student_id, course_id) VALUES (1, 10);

-- 全部うまくいったら
COMMIT;
-- エラーがあったら変更を元に戻す
ROLLBACK;

もしcourse_id = 10のコースがなかったら、studentsテーブルへの挿入もキャンセルされるよ。

トランザクション内でのエラー処理

PostgreSQLでは、エラーを予測してEXCEPTIONブロックを使ってクエリ内で処理できるんだ。

例:学生を追加してコースに登録する。エラーが起きたらログに記録する。

DO $$
BEGIN
    -- データ挿入を試す
    INSERT INTO students (name, age) VALUES ('Anna Song', 22);
    INSERT INTO enrollments (student_id, course_id) VALUES (2, 999); -- エラー

    -- 全部うまくいったら
    RAISE NOTICE 'レコードが正常に追加されたよ!';
EXCEPTION
    WHEN foreign_key_violation THEN
        -- 外部キー違反を処理
        RAISE WARNING '指定されたcourse_idのコースは存在しないよ。';
END $$;

ON CONFLICTでユニーク制約違反を防ぐ

UNIQUE制約違反のエラーは、ON CONFLICT構文で事前に防げるよ。どうするか指定できるんだ。

例:重複するコースを挿入しようとしたらスキップする。

INSERT INTO courses (course_name)
    VALUES ('SQL Basics')
ON CONFLICT (course_name) DO NOTHING; -- 重複データはスキップ

または既存の行を更新する:

INSERT INTO courses (course_name)
    VALUES ('SQL Basics')
ON CONFLICT (course_name) DO UPDATE     
    SET course_name = EXCLUDED.course_name || ' (Updated)';

ON CONFLICTオペレーターについては、次のレベルで大量データのロードをやるときにもっと詳しく話すね :P

データ操作でよくあるエラーとその防止法

もう見た通り、主なエラーの原因は:

  1. 制約違反(NOT NULLUNIQUEFOREIGN KEY)。
  2. データ更新や削除時にクエリにWHERE条件がない。
  3. トランザクションの実行順序ミス。

自分を守るために:

  • 大きな操作にはトランザクションとROLLBACKを使おう。
  • 挿入前にデータを必ずチェックしよう。
  • エラーはログに残して分析しよう。
  • 重複レコードを避けるためにON CONFLICTを使おう。

これでエラーと戦う知識はバッチリ!覚えておいて:いいエンジニアはミスしない人じゃなくて、ミスをちゃんと直せる人だよ。

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