Quantcast
Viewing all articles
Browse latest Browse all 100

"Out of range value for column 'カラム名' at 行番号" に対処した

開発業者が納品したWebアプリケーションがエラーを吐いていた。
致命的な問題で無かったことから発覚が遅れ、瑕疵担保責任を追及できる期間はとうに過ぎていたので、自分で直したという話。

調査ついでにエラーログの見方を簡単に説明しよう。

出力されたエラーメッセージ

_mysql_exceptions.DataError:(1264,"Out of range value for column 'カラム名' at row 1")

MySQLdbというPythonのモジュールが投げた例外のようだ。
最初の 1264は4桁なので、MySQL独自のエラーコードだろう。

2つのエラー番号

MySQLのエラー番号には、

  1. MySQL独自のエラーコード(4桁)
  2. ODBCやANSI SQLで定められたSQLSTATE(5桁)

がある。

SQLSTATEは汎化されているので、MySQLに特化した独自コードの方が詳細に特定できる。
公式サイトですべてのエラーメッセージを確認できるが、特に良く見かけるものを以下に抜粋する。

Row 行番号 doesn't contain data for all columns

  • エラーコード:1261
  • SQLSTATE:01000
  • 意味:すべてのカラムへのデータを含んでいない

Row 行番号 was truncated; it contained more data than there were input columns

  • エラーコード:1262
  • SQLSTATE:01000
  • 意味:カラムよりも多いデータを含んでいたので、切り捨てたデータがある

Column set to default value; NULL supplied to NOT NULL column 'カラム名' at row 行番号

  • エラーコード:1263
  • SQLSTATE:22004
  • 意味:NOT NULL のカラムにデフォルト値の NULL を登録した

Out of range value for column 'カラム名' at row 行番号

  • エラーコード:1264
  • SQLSTATE:22003
  • 意味:範囲外の値だったので、取り敢えず限界の値で登録した

▶ 今回出力されたエラーメッセージである。

Data truncated for column 'カラム名' at row 行番号

  • エラーコード:1265
  • SQLSTATE:01000
  • 意味:先頭からみて入れられるところまで登録し、残りは切り捨てた

つまり…

エラーコード 1264は、データ型の範囲を超えた値をINSERTしたときに発生するWarningである。直前に実行したSQLのWarningは SHOW WARNINGSで確認できる。
データ型の範囲を超えると、そのデータ型の最大値または最小値に調整されて登録されるはずだが、PythonがDataError例外を投げたのでrollbackされたと推測。実際にも登録されていなかった。

スタックトレース例
insertintozzzzz_tablevalues(5,1611728121,0,162,58.2,63.9,1,27.5)Traceback(mostrecentcalllast):File"/foo/bar/example.py",line547,in<module>fooList()File"/foo/bar/example.py",line164,inbarListcursor.execute(qstr)File"/usr/lib/python2.7/dist-packages/MySQLdb/cursors.py",line226,inexecuteself.errorhandler(self,exc,value)File"/usr/lib/python2.7/dist-packages/MySQLdb/connections.py",line36,indefaulterrorhandlerraiseerrorvalue_mysql_exceptions.DataError:(1264,"Out of range value for column 'xxxxx' at row 1")

データ型

対象カラムのデータ型をDESCで確認するとTINYINTであった。
TINYINTの取りうる範囲は次の通り。

  • バイト数: 1バイト
  • デフォルト桁数: tinyint(4)
  • 符号付き(SIGNED)の範囲:-128 ~ 127

データ型の後にUNSIGNEDを付けると符号なしとなり、0~255の範囲になる。
ちなみに tinyint(1) はBoolean型と同じだ。

直前のSQLで127を超える値をINSERTしていたが、運用上ありえない値なのでソースコードを修正した。


Viewing all articles
Browse latest Browse all 100

Trending Articles