Q1本講座のコンソールで、INTEGERを宣言した列に文字列'123'を INSERT したときの説明として正しいものはどれですか。
文字列・数値・論理型と暗黙の型変換
この記事は、基礎から複雑なSQL,SQLチューニングまでSQLの実践的なスキルを1からマスターする「SQL入門講座の一部」です。
typed_demoテーブルを題材に、宣言型と格納クラス、typeof()で見る '10' と123の相互変換、真偽を0 / 1で表すしくみ、そしてMySQLのCHAR/VARCHAR/INT/DECIMALの厳格型との違いを実際に動かして確かめます。
本記事で使うデータ — typed_demo テーブル
列を作るときINTEGER / TEXT / REALのような型を宣言し、その列に入る値の扱いを決めます。
本記事では、文字列・数値・論理(真偽)の 3 つの値が SQL でどう保存・比較されるか、そして本講座のコンソールが採用する型の扱い方が MySQL の厳格な型とどう違うかを順に確認します。
宣言された型と格納クラス — 値そのものが型を持つ
値が実際に持つ型を格納クラス(storage class)と呼び、NULL / INTEGER(整数)/ REAL(小数)/ TEXT(文字列)/ BLOB(バイナリ)の 5 種類があります。
ある値が現在どの格納クラスかはtypeof(値)関数で確認できます。
TEXTを宣言した列に数値らしい文字列を入れても、その列の方針が「文字列として扱う」なので文字列のまま保持されます。
一方、INTEGERを宣言した列に'123'のような数値らしい文字列を入れると、列の方針に従って整数123に変換されてから格納されます。
-- 別テーブルで「列の宣言型が値の格納型を決める」ことを観察する例
-- INTEGER 列に数値らしい文字列を入れると整数化される
CREATE TABLE IF NOT EXISTS aff_probe(num INTEGER, txt TEXT);
INSERT OR IGNORE INTO aff_probe VALUES ('123','123'), ('hello','hello');
-- typeof で実際の格納クラスを確認
SELECT num, typeof(num) AS num_class,
txt, typeof(txt) AS txt_class
FROM aff_probe;
-- num 列: '123' は integer に変換、'hello' は数値化できず text のまま
-- txt 列: どちらも text のまま
文字列と数値の相互変換 — '123' と 123 を行き来する
数値が必要な場面では文字列が自動的に数値へ、文字列が必要な場面では数値が文字列へ変換されます。
たとえば'123' + 0は文字列'123'が数値123に変換されて123を返し、算術演算では数値らしい文字列がそのまま計算に使えます。
逆に123 || ''(||は文字列連結)では数値が文字列になります。
比較演算でも、片方がINTEGER列なら相手も数値として揃え、片方がTEXT列なら相手も文字列として揃えて比べます。
ただし列を介さずリテラルだけを比べる'1' = 1は数値方針が働かず、種類違いとして0(不一致)になります。
-- 文字列 <-> 数値 の変換を観察(読むだけの別例)
SELECT '123' + 0 AS str_to_num, -- 文字列が数値 123 に
'abc' + 0 AS not_a_num, -- 数値化できず 0
123 || '' AS num_to_str, -- 数値が文字列 '123' に
typeof('123' + 0) AS class_after_add,
'1' = 1 AS literal_cmp, -- リテラルどうしは 0 (不一致)
7 / 2 AS int_div, -- 整数 / 整数 = 整数 3
7.0 / 2 AS real_div; -- 小数が混ざると 3.5
論理(真偽)型 — TRUE / FALSE は 1 / 0 で表す
SQL には独立した論理型がなく、真偽は整数の1(真)と0(偽)で表します。
1 = 1や3 > 2のような比較式は、真なら1、偽なら0を返します。
CASE WHEN 列 THEN ...のように条件式が書ける場所では、0以外(典型的には1)が真、0が偽として扱われます。
NULLは真でも偽でもない第 3 の状態(不明)で、WHEREやCASEの条件としては偽と同じく「採用されない」扱いになります。
-- 比較式は 1 / 0 を返す(読むだけの別例)
SELECT (1 = 1) AS is_true, -- 1
(1 = 2) AS is_false, -- 0
(3 > 2) AS gt, -- 1
TRUE AS true_kw, -- 1 と同じ
FALSE AS false_kw; -- 0 と同じ
-- フラグ列をそのまま条件に使う
SELECT a, flag,
CASE WHEN flag THEN 'enabled' ELSE 'disabled' END AS state
FROM typed_demo;
MySQL の厳格な型との対比
ここまで見た暗黙の型変換は、数値らしい文字列を場面に応じて柔軟に変換する扱い方です。
一方MySQL や Oracle では型がより厳格で、CHAR(10) / VARCHAR(255) / TEXTの文字列型、INT / DECIMAL(10,2)の数値型を宣言すると、その列にはその型の値だけが入り、桁数や精度も宣言どおりに守られます。
文字列型に数値が暗黙変換されて入ることは原則なく、長さを超える値はエラーになるか切り詰められます。
下のコードは MySQL での型宣言の書き方です。
本講座のコンソールでは桁数チェックが出ない設計なので、VARCHAR(10)のような長さ制約を学ぶときは「MySQL ではこう書く」という形で覚えておくと、別の DB に移ったときにそのまま通用します。
-- MySQL での厳格な型宣言(読むだけ。このコンソールでは実行しない)
CREATE TABLE product (
id INT PRIMARY KEY, -- 整数のみ
code CHAR(8), -- 固定長 8 文字
name VARCHAR(100) NOT NULL, -- 最大 100 文字
note TEXT, -- 長い文字列
price DECIMAL(10,2) NOT NULL, -- 整数 8 桁 + 小数 2 桁
in_stock TINYINT(1) DEFAULT 0 -- 0/1 で真偽を表すフラグ
);
-- MySQL では VARCHAR(100) に 101 文字を入れると
-- エラーになるか設定により切り詰められる。
-- INT 列に 'abc' を入れようとするとエラーになる。
-- 本講座のコンソールでは暗黙の型変換により実行自体は通る。
Tips — CHAR と VARCHAR の違いと使い分け
`CHAR(n)` は固定長で、入れた値が n 文字未満なら末尾に空白を詰めて n 文字に揃えます。
`VARCHAR(n)` は可変長で、入れた値の長さそのままを保持します(n は上限)。
`CHAR` を選ぶのは: 国コード('JP' / 'US')、性別コード、ハッシュ値の固定長部分など、長さが常に固定で揃っている値を入れる列。固定長なので比較やレコード位置計算がわずかに速い場面があります。
`VARCHAR` を選ぶのは: 名前・メールアドレス・タイトル・説明文など、長さがばらつく値を入れる列。実際に必要な分しか領域を取らないため、保存サイズが小さくなります。
迷ったら `VARCHAR` が無難です。CHAR を可変長データに使うと、末尾の空白詰めで意図しない比較ズレ('JP' と 'JP ' の扱いの違い)を起こすことがあります。
理解度チェック
まずは1問ずつ答えてみましょう。
Q2SQL における真偽(論理値)の表し方として正しいものはどれですか。
Q3本講座のコンソールの暗黙の型変換と、MySQL の厳格な型の違いとして正しいものはどれですか。