読者です 読者をやめる 読者になる 読者になる

うまとま君の技術めも

2015年新卒入社した社畜の勉強内容などなど

sequelizeでidに0が入ってしまう

MySQL Node.js

sequelizeでidに0が入ってしまう

環境

概要

SequelizeでdialectとしてMySQLをした際に、 AUTO_INCREMENTカラムを含むテーブルに対してINSERTすると0が入ってしまう可能性がある。

Sequelize

SequelizeはNode.js用のORMである。

まず、下記のようなテーブルがあるとする

CREATE TABLE `Users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

ここで、sequelizeで定義したModelからnameカラムのみを指定してinsertすると 下記のようなSQLが発行される

INSERT INTO `Users` (`id`,`name`) VALUES (DEFAULT,'sequelize');

この時、設定によってはUsersに追加されるレコードは下記のようなものになる場合がある

select * from Users;
+----+-----------+
| id | name      |
+----+-----------+
|  0 | sequelize |
+----+-----------+

NO_AUTO_VALUE_ON_ZERO

MySQLではsql_modeという設定があります。

https://dev.mysql.com/doc/refman/5.6/ja/faqs-sql-modes.html

  1. サーバー SQL モードとは何ですか。
  2. サーバー SQL モードは、MySQL でサポートされる SQL 構文、および実行されるデータ妥当性チェックの種類を定義します。

sql_modeの1つにNO_AUTO_VALUE_ON_ZEROがあり、 これを設定すると、INSERT時にAUTO_INCREMENTカラムに対して0を指定しても自動採番されなくなります。

NO_AUTO_VALUE_ON_ZERO は AUTO_INCREMENT カラムの処理に影響します。通常は、NULL または 0 をカラムに挿入することによって、カラムの次のシーケンス番号を生成します。NO_AUTO_VALUE_ON_ZERO は 0 のこの動作を抑制するため、NULL のみが次のシーケンス番号を生成します。

https://dev.mysql.com/doc/refman/5.6/ja/sql-mode.html

また、MySQLでは数値型の初期値は0なので、DEFAULTは0にります。 https://dev.mysql.com/doc/refman/5.6/ja/data-type-defaults.html

なので、NO_AUTO_VALUE_ON_ZEROを設定している状態でidに対してDEFAULTを指定すると 必ずidに0が入るようになってしまいます。

対応

下記SQLsql_modeを確認、設定することができます。 状況に応じて、適切なsql_modeを設定すれば良さそう?

SELECT @@GLOBAL.sql_mode;
SELECT @@SESSION.sql_mode;

SET GLOBAL sql_mode = 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION';
SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION';

まとめ

Sequelizeを使うときは、sql_modeの設定を事前に確認しましょう。 MySQLに対しての知識が全然ないので、地味にハマりました。。。