Postgresは、MySQLとは少し異なる方法で自動インクリメントを処理します。 Postgresで、serial
を作成するとき フィールドでは、使用するIDを追跡するシーケンスフィールドも作成しています。このシーケンスフィールドは、値1で始まります。
id
を指定しない場合、テーブルに新しいレコードを挿入するとき フィールドでは、シーケンスの値を使用してから、シーケンスをインクリメントします。ただし、id
を指定した場合 フィールドの場合、シーケンスは使用されず、更新もされません。
Postgresに移行したときに、既存のユーザーとその既存のIDをシードまたはインポートしたと思います。これらのユーザーレコードをIDで作成した場合、シーケンスは使用されなかったため、更新されませんでした。
したがって、たとえば、10人のユーザーをインポートした場合、IDが1〜10のユーザーがいますが、シーケンスは1のままです。IDを指定せずに新しいユーザーを作成しようとすると、シーケンスから値が取得されます( 1)、ID 1のユーザーがすでにいるため、一意の違反が発生します。
この問題を解決するには、users_id_seq
を設定する必要があります 既存のユーザーのMAX(id)へのシーケンス値。シーケンスのリセットの詳細については、この質問/回答を読むことができますが、(テストされていない)のようなものを試すこともできます:
SELECT setval(pg_get_serial_sequence('users', 'id'), coalesce(max(id)+1, 1), false) FROM users;
参考までに、これはMySQLの問題ではありません。これは、値が自動インクリメントフィールドに手動で挿入されると、MySQLが自動インクリメントシーケンスを最大の列値に自動的に更新するためです。