MySQL 10 min read

MySQLの型変換 ― 文字列と数値のCAST、AS INTが通らない・黙って0になる値

※この記事にはアフィリエイト広告(プロモーション)が含まれます。

この記事の出力は MySQL 8.4.11(Ubuntu 26.04、sql_mode は既定)で採りました。

まず見る(結論)

SELECT CAST('123' AS SIGNED);            -- 123(整数)
SELECT CAST('123' AS UNSIGNED);          -- 123(符号なし整数)
SELECT CONVERT('123', SIGNED);           -- 123(CAST と同じ)
SELECT CAST('12.345' AS DECIMAL(10,2));  -- 12.35
SELECT CAST(123 AS CHAR);                -- '123'
SELECT LPAD(5, 5, '0');                  -- '00005'
  • CAST('123' AS INT) と AS INTEGER は ERROR 1064。整数は SIGNED か UNSIGNED(SIGNED INTEGER は通る)
  • 変換できない文字列はエラーにならず 0 や途中までの数になる。出るのは警告 1292 だけ

CAST で指定できる型

指定 CAST('123' AS …)
SIGNED / SIGNED INTEGER / UNSIGNED 123
DECIMAL / DECIMAL(10,2) 123 / 123.00
FLOAT / DOUBLE 123
CHAR ‘123’

CAST の型は列の型と同じ名前ではありません。DECIMAL を桁なしで書くと DECIMAL(10,0) になり、CAST('12.5' AS DECIMAL) は 13 でした。

変換できない文字列の結果

式 結果
CAST(' 123 ' AS SIGNED) 123
CAST('1,234' AS SIGNED) 1
CAST('123abc' AS SIGNED) 123
CAST('abc' AS SIGNED) / CAST('' AS SIGNED) 0
CAST('123' AS SIGNED)(全角) 0
CAST('1e3' AS SIGNED) 1('1e3' + 0 と AS DECIMAL は 1000)
CAST('99999999999999999999' AS SIGNED) -1
CAST(-1 AS UNSIGNED) 18446744073709551615

先頭から数として読める所までを使い、残りを捨てます。SHOW WARNINGS に Warning 1292 Truncated incorrect INTEGER value: '1,234' が出るだけです(CAST(-1 AS UNSIGNED) は警告も出ません)。PostgreSQL はこれらを全部エラーにします(PostgreSQLの型変換)。

文字列の小数と数値の小数で丸めが違う

式 結果
CAST('12.5' AS SIGNED) 12
CAST(12.5 AS SIGNED) / CAST(-12.5 AS SIGNED) 13 / -13
CAST(CAST('12.5' AS DECIMAL(10,1)) AS SIGNED) 13
ROUND('12.5') / ROUND(12.5) 12 / 13

ROUND に文字列を渡すと DOUBLE として計算されます。四捨五入したいなら先に DECIMAL にします。

カンマ入り・全角の文字列

SELECT CAST(REPLACE('1,234', ',', '') AS SIGNED);   -- 1234
SELECT CAST(FORMAT(1234567.891, 2) AS DECIMAL(12,2));  -- 1.00(FORMAT の結果は戻せない)

全角数字は MySQL の関数だけでは変換できないので、取り込む前に半角にそろえます。

暗黙の変換(+ 0 と比較)

文字列に + 0 すると数値になります。'123abc' + 0 は 123、'abc' + 0 は 0 で、警告は Truncated incorrect DOUBLE value です。'10' + '20' は 30 です。文字列をつなぐのは CONCAT で、10 || 20 は 1(論理和)でした。

文字列の列を数値で検索すると

索引のある code(varchar)に '10' '10abc' ' 10' '08' などを入れて比べました。

SQL 返った行 EXPLAIN
WHERE code = 10 '10' '10abc' ' 10' type: ALL(key は NULL)
WHERE code = '10' '10' type: ref(key: code)
WHERE code = 8 '08' —

文字列の列と数値を比べると、列の値を1行ずつ数値に変換してから比較します。文字列の列には文字列('10')で条件を書きます。EXPLAIN の見方は EXPLAIN の記事に書きました。

数字の文字列を数値順に並べる

ORDER BY 並び
code ‘ 10’, 08, 10, 100, 10abc, 2, 9
code + 0, code 2, 08, 9, ‘ 10’, 10, 10abc, 100
CAST(code AS UNSIGNED), code 上と同じ
LENGTH(code), code 2, 9, 08, 10, ‘ 10’, 100, 10abc

LENGTH で並べる方法は、'08' のような 0 始まりや空白が混ざると崩れます。

SUM・INSERT・列の型変更

  • SUM(amount_txt) は '1,200' を 1、'abc' を 0 として足し、警告を出すだけで 863 を返した。正しい合計(2062)は SUM(REPLACE(amount_txt, ',', '')) を WHERE REPLACE(amount_txt, ',', '') REGEXP '^[0-9]+$' で数字だけの行に絞って求めた
  • int 列への INSERT は既定の sql_mode(STRICT_TRANS_TABLES あり)で '12abc' が ERROR 1265 Data truncated、'' が ERROR 1366 Incorrect integer value。'12.5' は 13、' 12 ' は 12 で入った
  • sql_mode = '' にすると '12abc' は 12、'' は 0 で、警告付きで入る
  • ALTER TABLE codes MODIFY code int は数字以外の行があると ERROR 1265 Data truncated for column 'code' at row 6。先に UPDATE ... WHERE code NOT REGEXP '^[0-9]+$' で直すと通り、'08' は 8 になった(ALTER TABLE の記事)

数値 → 文字列・0埋め

SELECT CONCAT(123, '');            -- '123'
SELECT LPAD(123456, 5, '0');       -- '12345'(長いと右が切れる)
SELECT FORMAT(1234567.891, 2);     -- '1,234,567.89'

LPAD を使うときは、値が指定した長さに収まるかを先に確かめます。

割り算と日付

  • 7 / 2 は 3.5000(小数4桁は div_precision_increment の既定値)。整数の商は 7 DIV 2 で 3。CAST(7 / 2 AS SIGNED) は 4(四捨五入)
  • CAST('2026/11/08' AS DATE) は通るが、8.4 では区切りの / に警告 4095(非推奨)が出る。CAST('2026-02-30' AS DATE) は警告付きで NULL。書式が決まっている文字列は STR_TO_DATE を使う(DATE_FORMAT の記事)

関連: MySQLの文字列結合 / ERROR 1366「Incorrect string value」 / MySQLの日付計算

MySQL をもっと深く知るための本

MySQL徹底入門 第5版 MySQL 8.4 LTS対応

翔泳社・2025年6月・MySQL 8.4 LTS 対応

MySQL 8.4 に対応した入門書。日本MySQLユーザ会のメンバーが執筆している。

Amazonで見る

MySQL運用・管理[実践]入門 〜安全かつ高速にデータを扱う内部構造・動作原理を学ぶ

技術評論社・2024年5月

内部構造と動作原理から、運用・管理の考え方を学ぶ。

Amazonで見る

Amazonのアソシエイトとして、FIRE SE は適格販売により収入を得ています。