4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

SQLAlchemyのIntegrityErrorを一意制約違反の例外としてexceptしてはいけない

Last updated at Posted at 2022-09-15

はじめに

SQLAlchemyで一意制約違反した時に、以下のようなエラーが発生します。

sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: user.email_address

一見、 IntegrityErrorの例外をexceptで囲んで一意制約違反の例外として処理したくなります。
しかしこれはNGです。

なぜNGなのか

IntegrityErrorは一意制約違反のエラーではなくDBのエラー全般をラップしたエラーだからです。
つまり一意制約違反以外にもNOT NULL制約違反外部キー制約違反IntegrityErrorになります。

以下は悪い例です。

悪い例

def create_user(session, user_name, email):
        try:
            user = User(user_name=user_name, email=email)
            session.add(user)
            session.commit()
            session.reflesh()

        except IntegrityError:
            session.rollback()
            raise HTTPException(status=400, detail="email is already exist.")

emailの一意制約違反と決めてつけていますが、もしかすると別のカラムがNOT NULL制約に違反しているのかもしれません。

どうするべきか

IntegrityErrorが保持しているオリジナルのエラーをexceptしてあげると良いです。
例えば以下のような感じです。(FastAPIとpsycopg2を例に用いています。)

crud.py
def create_user(session, user_name, email):
        try:
            user = User(user_name=user_name, email=email)
            session.add(user)
            session.commit()
            session.reflesh()

        except IntegrityError as sqlalchemy_error:
            session.rollback()
            raise sqlalchemy_error.orig # DatabaseごとのAPIのエラーをraiseする

main.py

from psycopg2 import errors as psycopg2_errors

@app.post("/users/")
def create_user(user: schemas.UserCreate, db: Session = Depends(get_db)):
    try:
        created_user = crud.create_user(
            session=db, 
            user_name=user.user_name,
            email=user.email
        )
        return created_user
    
    except psycopg2_errors.UniqueViolation:
        raise HTTPException(status=400, detail="email is already exist.")
    
    except psycopg2_errors.NotNullViolation:
        raise HTTPException(status=400, detail="invalid parameters.")

参考

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?