node-mysqlでBIGINTな整数を扱う際の問題と対処
この記事は最終更新日から1年以上が経過しています。
芽萌丸プログラミング部@programming
投稿日 2020/6/26
更新日 2020/6/26 ✏

node-mysqlでBIGINTな整数を扱う際の問題と対処

目次:

問題

Node.js(node-mysqlモジュール)でMySQLのBIGINTな整数値を扱う際には、数値の「丸め」に気をつける必要があります。 Node.js上でMySQLから取得したBIGINTな値は、JSの整数型の限界を超えると勝手に丸められてしまうからです。

以下に再現コードと対処方法を記載します。

再現と対処

準備

まずはテキトーにtestテーブルを作ります:

mysql>
-- BIGINTなカラムを持つtestテーブルを作成:
CREATE TABLE `test` (
  `id` bigint(20),
  PRIMARY KEY (`id`)
);
-- BIGINTのMAX値をINSERT:
INSERT INTO `test`(`id`) VALUES(9223372036854775807);

再現コード: BIGINTなカラムの値が丸められてしまう例

const mysql = require("mysql");

const conn = mysql.createConnection({
  host: 'localhost',
  user: 'hoge',
  password: 'pass',
  database: 'test',
});

conn.connect();

conn.query("SELECT `id` FROM `test`", (error, results, fields) => {
  console.log("result:", results);
  // result: [ RowDataPacket { id: 9223372036854776000 } ]
  // JSの数値型の精度により、9223372036854775807 が 9223372036854776000 に丸められてしまっている!
});

conn.end();

標準出力されたresultsの値を見てみると、本来 9223372036854775807なはずの値が、JSの整数型の精度の限界により 9223372036854776000に丸められてしまっています!

この問題を防ぐためには次のようにします。

対処方法: BIGINTなカラムの値が丸められてしまうのを防ぐ例

これを防ぐためには、BIGINTなカラムの値を文字列として扱います。createConnection()等のnode-mysqlのコネクション取得関数のパラメータに以下の値を設定します:

supportBigNumbers: true, // BigNumberサポート有効化
bigNumberStrings: true, // BigNumberを文字列として扱う

全体的なコードはこのようになります:

const mysql = require("mysql");

const conn = mysql.createConnection({
  host: 'localhost',
  user: 'hoge',
  password: 'pass',
  database: 'test',
  // NOTE: 下記の2つのプロパティをtrueにすればOK!
  supportBigNumbers: true, // BigNumberサポート有効化
  bigNumberStrings: true, // BigNumberを文字列として扱う
});

conn.connect();

conn.query("SELECT `id` FROM `test`", (error, results, fields) => {
  console.log("result:", results);
  // result: [ RowDataPacket { id: '9223372036854775807' } ]
  // OK!
});

conn.end();

標準出力されたresultsの値を見ると、本来の値9223372036854775807が正しく出力されています。

BIGINTな整数値をIDなどとして使う場合は特に注意しましょう。

以上です。


芽萌丸プログラミング部
芽萌丸プログラミング部@programming
プログラミング関連アカウント。Web標準技術を中心に書いていきます。フロントエンドからサーバサイドまで JavaScript だけで済ませたい人たちの集いです。記事は主に @TanakaSoftwareLab が担当。