0
0

SQLAlchemyで作成したテーブルのautoincrementについて

Last updated at Posted at 2023-12-07

はじめに

本記事はalembicとSQLAlchemyを使用してマイグレーションを管理しているプロジェクトで新規テーブルを追加した際に発生したことをまとめた備忘録です。

環境

Python 3.11.5
alembic 1.13.0
SQLAlchemy 2.0.23

mysql 8.0.34

何があったの?

とある目的で別テーブルで管理しているIDをPKにしたテーブルを作成することになりました。
他テーブルのPKをそのままPKとして使用するためautoincrementはFalseにする必要がありました。
ユーザー登録をする際はまずusersにレコードが生成されて、その生成されたレコードのPKをそのままuser_detailsのPKにする想定。
以下は実際に発生した事象を再現したものになります。

既存のテーブル
class User(Base):
    __tablename__ = 'users'

    id = Column(BIGINT, primary_key=True, autoincrement=True)
    last_name = Column(VARCHAR(16))
    first_name = Column(VARCHAR(16))
以下、マイグレーションにより実際に作成されたusersテーブル
+------------+-------------+------+-----+---------+----------------+
| Field      | Type        | Null | Key | Default | Extra          |
+------------+-------------+------+-----+---------+----------------+
| id         | bigint      | NO   | PRI | NULL    | auto_increment |
| last_name  | varchar(16) | YES  |     | NULL    |                |
| first_name | varchar(16) | YES  |     | NULL    |                |
+------------+-------------+------+-----+---------+----------------+
追加のテーブル
class UserDetail(Base):
    __tablename__ = 'user_details'

    user_id = Column(BIGINT, primary_key=True)
    height = Column(INTEGER)
    weight = Column(INTEGER)
以下、マイグレーションにより追加されたuser_detailsテーブル
+---------+--------+------+-----+---------+----------------+
| Field   | Type   | Null | Key | Default | Extra          |
+---------+--------+------+-----+---------+----------------+
| user_id | bigint | NO   | PRI | NULL    | auto_increment |
| height  | int    | YES  |     | NULL    |                |
| weight  | int    | YES  |     | NULL    |                |
+---------+--------+------+-----+---------+----------------+

ここであれっ?てなりました。
user_detailsの定義にはPKであるuser_idのautoincrementは何も指定していないのに勝手にautoincrementされる設定になってる...

対応

まずは公式ドキュメントを確認。
https://docs.sqlalchemy.org/en/20/core/metadata.html#sqlalchemy.schema.Column.params.autoincrement

以下、該当部分の引用

The default value is the string "auto", which indicates that a single-column (i.e. non-composite) primary key that is of an INTEGER type with no other client-side or server-side default constructs indicated should receive auto increment semantics automatically. Other values include True (force this column to have auto-increment semantics for a composite primary key as well), False (this column should never have auto-increment semantics), and the string "ignore_fk" (special-case for foreign key columns, see below).

autoincrementのデフォルト値ってFalseじゃないんだ!!
autoincrementのデフォルトは'auto'でINT型(もっと言うとINT, SMALLINT, BIGINT)でかつ、複合主キーでなければ自動的にオートインクリメントされる設定になるみたいでした。

なので明示的にautoincrementをFalseにするとauto_incrementが外れました。

追加のテーブル(修正版)
class UserDetail(Base):
    __tablename__ = 'user_details'

    user_id = Column(BIGINT, primary_key=True, autoincrement=False)
    height = Column(INTEGER)
    weight = Column(INTEGER)
以下、マイグレーションにより追加された修正版のuser_detailsテーブル
+---------+--------+------+-----+---------+-------+
| Field   | Type   | Null | Key | Default | Extra |
+---------+--------+------+-----+---------+-------+
| user_id | bigint | NO   | PRI | NULL    |       |
| height  | int    | YES  |     | NULL    |       |
| weight  | int    | YES  |     | NULL    |       |
+---------+--------+------+-----+---------+-------+

めでたしめでたし。

参考文献

0
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
0
0