MySQLエラー1292「Truncated incorrect DOUBLE value」をUPATEで修正する方法

intermediate🗄️ MySQL2026-05-21| MySQL 5.7+、MySQL 8.0+、MariaDB 10.x — OS不問(Linux、macOS、Windows)、クライアント不問(mysql CLI、DBeaver、phpMyAdmin、アプリケーションORM)

Error Message

ERROR 1292 (22007): Truncated incorrect DOUBLE value: 'some_string_value'
#mysql#update#データ型#sqlエラー

エラーはUPDATEの途中で発生する

いつも通りのUPDATEを実行すると、MySQLが次のエラーを返します:

ERROR 1292 (22007): Truncated incorrect DOUBLE value: 'active'

カラムは存在する。構文も問題ない。明らかな原因も見当たらない。何が起きているかというと、MySQLがクエリ内のどこかで文字列をDOUBLEにキャストしようとしているのです。ストリクトモードが有効な場合、MySQLは不正な値を黙って飲み込まず、代わりにエラーを返します。

なぜこのエラーが発生するか

エラー1292は、MySQLが文字列を数値型(INT、DOUBLE、FLOAT、DECIMAL)に変換しようとして、その文字列が有効な数値でない場合に発生します。MySQL 5.6以前では、この変換は黙って0に切り捨てられていました。MySQL 5.7以降、STRICT_TRANS_TABLESがデフォルトで有効になっています。そのため、切り捨ては静かなデータ破損ではなくエラーとして扱われます。

多くの人が見落とすポイント:問題の値はSET句ではなくWHERE句にあることがよくあります。

デバッグ:実際の原因を特定する

ステップ1 — 現在のsql_modeを確認する

SELECT @@sql_mode;

出力にSTRICT_TRANS_TABLESまたはSTRICT_ALL_TABLESが含まれていますか?それがMySQLが暗黙変換せずにエラーを出す理由です。無効化せず、クエリを修正してください。

ステップ2 — 関連するカラムの型を確認する

DESCRIBE your_table;
-- または
SHOW COLUMNS FROM your_table;

UPDATEで参照しているすべてのカラム(SETWHEREの両方)を確認してください。INTDOUBLEFLOATDECIMAL型のカラムに文字列値を比較または代入しているものが候補です。

ステップ3 — 問題の句を特定する

複雑なWHERE句がある場合は、先にSELECTとして実行してみましょう:

SELECT * FROM orders
WHERE status = 'active'
  AND category_id = 'electronics';

category_idがINTカラムであれば、このSELECTも同じ1292エラーを発生させます。これが原因です。

よくあるシナリオと修正方法

シナリオ1:数値カラムのWHERE句に文字列値を指定している

ほとんどの場合、これが原因です。数値の外部キーやステータスコードを文字列リテラルでフィルタリングしています。

-- 誤り: category_idはINTなのに文字列を渡している
UPDATE products
SET price = price * 0.9
WHERE category_id = 'electronics';

-- 修正: 実際の整数IDを使用する
UPDATE products
SET price = price * 0.9
WHERE category_id = 5;

シナリオ2:SET句で数値カラムに文字列を代入している

-- 誤り: stockはINT型
UPDATE inventory
SET stock = 'none'
WHERE product_id = 42;

-- 修正: 代わりに0またはNULLを使用する
UPDATE inventory
SET stock = 0
WHERE product_id = 42;

-- またはカラムがテキストを格納すべき場合は型を変更する
ALTER TABLE inventory MODIFY stock VARCHAR(20);

シナリオ3:論理演算子の誤用(&&、||)

MySQLの&&||演算子は両辺をDOUBLEに強制変換します。文字列のオペランドを渡すと即座に1292エラーが発生します。

-- 誤り: MySQLが'active'をDOUBLEにキャストしようとする
UPDATE orders
SET processed = 1
WHERE is_paid = 1 && status = 'active';

-- 修正: &&の代わりにANDを使用する
UPDATE orders
SET processed = 1
WHERE is_paid = 1 AND status = 'active';

シナリオ4:アプリケーション/ORMから文字列が渡されている

クエリ単体では問題なく見える。問題は実行時にバインドされるパラメータにあります。アプリケーションが実際にその値をどこで生成しているか確認してください。

-- 問題が発生するPython SQLAlchemyの例
db.execute(
    "UPDATE users SET role_id = :role WHERE id = :id",
    {"role": "admin", "id": user_id}  # role_idはVARCHARではなくINT
)

-- 修正: 正しい型を渡す
db.execute(
    "UPDATE users SET role_id = :role WHERE id = :id",
    {"role": 3, "id": user_id}  # 'admin'ロールの整数ID
)

シナリオ5:型が混在するカラムでの算術演算

-- 誤り: discountはVARCHAR('10%')なのでMySQLが文字列を乗算しようとする
UPDATE orders
SET final_price = base_price * (1 - discount)
WHERE id = 101;

-- 修正: '%'を除去して明示的にキャストする
UPDATE orders
SET final_price = base_price * (1 - CAST(REPLACE(discount, '%', '') AS DECIMAL(5,2)) / 100)
WHERE id = 101;

今すぐリリースが必要な場合の一時的な回避策

変換されるデータの内容を正確に把握していて、直後にクリーンアップを行う場合のみ使用してください。

-- このセッションのみストリクトモードを緩和する
SET SESSION sql_mode = REPLACE(@@SESSION.sql_mode, 'STRICT_TRANS_TABLES', '');

-- UPDATEを実行する
UPDATE ...

-- ストリクトモードを元に戻す
SET SESSION sql_mode = @@GLOBAL.sql_mode;

ストリクトモードを無効にすると、MySQLは不正な変換を黙って0に切り捨てます。つまりprice = '10abc'は静かにprice = 10になり、status_code = 'active'status_code = 0になります。UPDATEが完了したら直ちに影響を受けた行を確認してください。

修正が正しく適用されたか確認する

-- 1. エラーなしでUPDATEを実行する
UPDATE orders SET processed = 1 WHERE is_paid = 1 AND status = 'active';
-- Query OK, N rows affected (0.01 sec)

-- 2. データが正しく変更されたか確認する
SELECT id, processed, status FROM orders
WHERE is_paid = 1 AND status = 'active'
LIMIT 10;

-- 3. 誤って0になった行がないか確認する
SELECT COUNT(*) FROM orders WHERE processed = 0 AND is_paid = 1 AND status = 'active';
-- 0が返るはず

長期的な対策:再発を防ぐために

  • **ストリクトモードを有効のままにする。**型の不一致をデータが静かに壊される前に検出してくれます。本番環境でこれを無効にして運用するのは、エラーログに何も残らないまま何千行ものprice = 0が生まれる原因になります。
  • **アプリケーション層で型を合わせる。**カラムがINTであれば、常に整数をバインドしてください。MySQLの暗黙キャストに頼って差異を埋めようとしないでください。
  • 複雑なWHERE句はまずSELECTとしてテストする本番テーブルに対してUPDATEを実行する前に確認しましょう。
  • **ORMではカラムマッピングを確認する。**モデル上の文字列フィールドがDB上のINTカラムにマッピングされている場合、アプリケーションコードの型チェックは通っても、DBレイヤーで静かに壊れます。
  • 型を混在させる式ではCAST()を明示的に使う変換を可視化して意図的なものにし、後でクエリを読む人にも明確に伝わるようにしましょう。

Related Error Notes