- 問題
- 修正作業
- プライマリキーとして設定
- 値の重複の解決
- 正しい設定をまとめると…
- Before
- After
問題
Django でモデルを扱う際、デフォルトで作成される id ではないプライマリキーで管理をしたかったので、なんとなくネットでささっと見た情報で 「models.AutoField(primary_key=True)」を設定していました。
ただ、データベース上での設定が正しくできていなかった様で自動インクリメントが機能していませんでした。
そのため Django の admin 画面からデータを登録する際、すでに存在する値が id として登録されていました。
ちなみに、models.py では「models.AutoField(primary_key=True)」となっていたもののテーブル上ではカラムがプライマリキーになっていなかったため、エラーにもなっていませんでした。
修正作業
この時点でのテーブルは下記の状態。「id」カラムを修正していきます。
mysql> describe ig_mst_product; +-------------------+--------------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------------------+--------------------------+------+-----+---------+-------+ | id | int(6) unsigned zerofill | NO | | 000000 | | | product_nm | varchar(60) | YES | | NULL | | | product_category | varchar(20) | YES | | NULL | | | brand_cd | int(6) unsigned zerofill | YES | | NULL | | | product_url | text | YES | | NULL | | | product_image_url | text | YES | | NULL | | +-------------------+--------------------------+------+-----+---------+-------+
プライマリキーとして設定
既存の値が再度使われてしまうのはおかしいので MySQL 上でプライマリキーを設定。
mysql> alter table ig_mst_brand add primary key (id);
値の重複の解決
admin 画面からレコードを追加すると「1062, "Duplicate entry '000000' for key 'ig_mst_product.PRIMARY'"」という感じで値の重複が発生。
「000000」を id として使用しようとしているので、おそらく値の自動インクレメントがされていない状態。
デフォルト値の設定削除
デフォルト値として「000000」を設定していたのでとりあえずなくしてみます。
mysql> alter table ig_mst_product alter id drop default;
auto_increment の設定
その上で MySQL でカラムに auto_increment を設定しようとしたところ、また値の重複で拒否されました。
mysql> alter table テーブル名 modify カラム名 int(6) unsigned zerofill not null auto_increment; ERROR 1062 (23000): ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '000001' for key 'テーブル名.PRIMARY'
この時点で id カラムには「000000」〜「000069」まで存在していたにもかかわらず、なぜか「000001」を使おうとして重複エラーが返ってきている状況。
調べてみたところ、既存データの対象のカラムの中に 0 もしくは -1 以下の値が入っているとこのエラーになる様です。既存データで「000000」が存在したのでこれを別の値に変更して再度実行したら成功しました。
mysql> alter table ig_mst_product modify id int(6) unsigned zerofill not null auto_increment; Query OK, 69 rows affected, 2 warnings (0.04 sec) Records: 69 Duplicates: 0 Warnings: 2
正しい設定をまとめると…
Id として使用するカラムがデータベース上で下記の条件を満たす必要がある様です。
- デフォルト値なし
- プライマリキーとして設定
- AUTO_INCREMENT を設定
- 既存データで 0 もしくはそれ以下の値が入っていないことを確認
一応 Before / After も載せておきます。Key, Default, Extra が変わっています。
Before
mysql> describe ig_mst_product; +-------------------+--------------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------------------+--------------------------+------+-----+---------+-------+ | id | int(6) unsigned zerofill | NO | | 000000 | | | product_nm | varchar(60) | YES | | NULL | | | product_category | varchar(20) | YES | | NULL | | | brand_cd | int(6) unsigned zerofill | YES | | NULL | | | product_url | text | YES | | NULL | | | product_image_url | text | YES | | NULL | | +-------------------+--------------------------+------+-----+---------+-------+
After
mysql> describe ig_mst_product; +-------------------+--------------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------------+--------------------------+------+-----+---------+----------------+ | id | int(6) unsigned zerofill | NO | PRI | NULL | auto_increment | | product_nm | varchar(60) | YES | | NULL | | | product_category | varchar(20) | YES | | NULL | | | brand_cd | int(6) unsigned zerofill | YES | | NULL | | | product_url | text | YES | | NULL | | | product_image_url | text | YES | | NULL | | +-------------------+--------------------------+------+-----+---------+----------------+