LENGTH関数は、SQLで文字列の長さを取得するための基本関数です。しかし、RDBMSによって「文字数」を返すのか「バイト数」を返すのかが異なるため、正しく理解していないとマルチバイト文字(日本語など)を扱う際に思わぬバグを生むことがあります。
この記事では、LENGTH関数の基本構文から、CHAR_LENGTH・OCTET_LENGTH・LEN・DATALENGTH との違い、RDBMS別の挙動比較、WHERE句やORDER BY・CASEとの組み合わせなど実務で使えるパターンまで、文字列長の取得に関する全体像を解説します。
💡 この記事でわかること
- LENGTH関数の基本構文と使い方
- LENGTH / CHAR_LENGTH / OCTET_LENGTH / LEN / DATALENGTH の違いと使い分け
- RDBMS別(MySQL・PostgreSQL・Oracle・SQL Server)の挙動の違い
- マルチバイト文字(日本語)での注意点
- WHERE / ORDER BY / CASE / GROUP BY との実務パターン
- NULLや空文字の扱い、パフォーマンスの注意点
LENGTH関数の基本構文
LENGTH関数は、引数に渡した文字列の「長さ」を数値で返します。
LENGTH(文字列)
-- リテラル文字列の長さを取得 SELECT LENGTH('Hello, World!'); -- 結果: 13 -- テーブルのカラム値の長さを取得 SELECT name, LENGTH(name) AS name_length FROM employees;
⚠ 重要: LENGTH関数が返す値はRDBMSによって異なります。MySQLではバイト数、PostgreSQL・Oracleでは文字数を返します。日本語などのマルチバイト文字を扱う場合、この違いは致命的です。詳しくは次のセクションで解説します。
文字列長を取得する関数の比較
SQLには文字列の長さを取得する関数が複数あり、RDBMSごとに利用できる関数が異なります。最も重要な違いは「文字数」を返すのか「バイト数」を返すのかです。
関数一覧と返却値の違い
マルチバイト文字での違いを確認
半角英数字では違いが見えませんが、日本語(マルチバイト文字)で比較すると関数の違いが明確になります。
-- MySQL(UTF-8環境)での実行結果 SELECT LENGTH('データベース') AS len_result, -- 15(バイト数: 5文字 × 3バイト) CHAR_LENGTH('データベース') AS charlen_result, -- 5(文字数) OCTET_LENGTH('データベース') AS octlen_result; -- 15(バイト数)
🚨 MySQLのLENGTHはバイト数を返す: MySQLの LENGTH() はUTF-8環境で日本語1文字を3バイトとしてカウントします。MySQLで文字数が欲しい場合は必ず CHAR_LENGTH() を使いましょう。
ℹ️ Oracleは空文字をNULLとして扱う: Oracleでは空文字列 '' は NULL と同等に扱われるため、LENGTH('') は 0 ではなく NULL を返します。これは Oracle 独自の仕様です。
RDBMS別の書き方
各RDBMSで「文字数」と「バイト数」を正しく取得する方法をまとめます。
MySQL
-- 文字数を取得(推奨) SELECT CHAR_LENGTH('データベース'); -- 結果: 5 -- バイト数を取得 SELECT LENGTH('データベース'); -- 結果: 15(UTF-8) -- OCTET_LENGTH は LENGTH と同じ(バイト数) SELECT OCTET_LENGTH('データベース'); -- 結果: 15 -- BIT_LENGTH はビット数を返す(バイト数 × 8) SELECT BIT_LENGTH('データベース'); -- 結果: 120(15バイト × 8)
PostgreSQL
-- 文字数を取得 SELECT LENGTH('データベース'); -- 結果: 5 SELECT CHAR_LENGTH('データベース'); -- 結果: 5 -- バイト数を取得 SELECT OCTET_LENGTH('データベース'); -- 結果: 15(UTF-8)
Oracle
-- 文字数を取得 SELECT LENGTH('データベース') FROM DUAL; -- 結果: 5 -- バイト数を取得 SELECT LENGTHB('データベース') FROM DUAL; -- 結果: 15(AL32UTF8)
Oracleの文字数・バイト数取得について詳しくは「Oracleで文字列の文字数・バイト数を取得する方法」をご覧ください。
SQL Server
-- 文字数を取得(末尾スペースを除外) SELECT LEN(N'データベース'); -- 結果: 5 -- バイト数を取得(末尾スペースを含む) SELECT DATALENGTH(N'データベース'); -- 結果: 10(nvarchar: 1文字2バイト) -- LEN の末尾スペース除外に注意 SELECT LEN(N'ABC '); -- 結果: 3(末尾スペースを除外) SELECT DATALENGTH(N'ABC '); -- 結果: 12(6文字 × 2バイト、スペース含む)
ℹ️ SQL Serverの注意点: LEN() は末尾のスペースをカウントしませんが、DATALENGTH() は末尾スペースもバイト数に含めます。また、nvarchar 型は1文字2バイト、varchar 型はエンコーディング依存です。
RDBMS別まとめ: 文字数を取得するならこの関数
WHERE句で文字数を条件にデータを抽出する
LENGTH関数をWHERE句で使うと、文字数を条件にしてレコードを絞り込めます。データのバリデーションや品質チェックに頻出するパターンです。
基本: 文字数が一定以上のデータを抽出
-- 名前が10文字以上の社員を取得(MySQL) SELECT employee_id, name FROM employees WHERE CHAR_LENGTH(name) >= 10; -- PostgreSQL / Oracle の場合 SELECT employee_id, name FROM employees WHERE LENGTH(name) >= 10;
データ品質チェック: 異常データの検出
-- 電話番号が10桁または11桁でないレコードを検出 SELECT customer_id, phone_number FROM customers WHERE CHAR_LENGTH(phone_number) NOT IN (10, 11); -- メールアドレスが短すぎるレコードを検出(x@y.z = 最短5文字) SELECT user_id, email FROM users WHERE CHAR_LENGTH(email) < 5; -- 郵便番号が7桁でないレコードを検出 SELECT address_id, postal_code FROM addresses WHERE CHAR_LENGTH(REPLACE(postal_code, '-', '')) <> 7;
✅ 実務ポイント: 郵便番号の例のように、REPLACE関数で不要な文字を除去してからLENGTH/CHAR_LENGTHで長さをチェックするパターンは、データクレンジングの定番テクニックです。
ORDER BY で文字数順にソートする
LENGTH関数をORDER BY句で使うと、文字列の長さ順でソートできます。
-- 商品名を文字数が少ない順にソート(MySQL) SELECT product_name, CHAR_LENGTH(product_name) AS name_length FROM products ORDER BY CHAR_LENGTH(product_name) ASC; -- 文字数が多い順にソート SELECT product_name, CHAR_LENGTH(product_name) AS name_length FROM products ORDER BY CHAR_LENGTH(product_name) DESC;
文字数を基準にしたソートの詳細パターンは「文字数をカウントして多い順や少ない順でソートする方法」で詳しく解説しています。
CASE文と組み合わせて文字数で分類する
CASE文と組み合わせることで、文字数に応じてデータを分類・ラベル付けできます。
-- コメントの文字数に応じてラベルを付ける(MySQL) SELECT comment_id, CHAR_LENGTH(comment_text) AS text_length, CASE WHEN CHAR_LENGTH(comment_text) < 50 THEN '短文' WHEN CHAR_LENGTH(comment_text) < 200 THEN '通常' WHEN CHAR_LENGTH(comment_text) < 1000 THEN '長文' ELSE '超長文' END AS length_category FROM comments;
GROUP BY と組み合わせて文字数別に集計
-- コメントを文字数カテゴリ別に件数集計(MySQL) SELECT CASE WHEN CHAR_LENGTH(comment_text) < 50 THEN '50文字未満' WHEN CHAR_LENGTH(comment_text) < 200 THEN '50〜199文字' WHEN CHAR_LENGTH(comment_text) < 1000 THEN '200〜999文字' ELSE '1000文字以上' END AS length_range, COUNT(*) AS cnt FROM comments GROUP BY length_range ORDER BY MIN(CHAR_LENGTH(comment_text));
他の文字列関数との組み合わせ
LENGTH関数は単体でも便利ですが、他の文字列関数と組み合わせることでさらに強力な処理が可能です。
TRIM + LENGTH: 前後の空白を除いた文字数
-- 前後の空白を除いた実質的な文字数を取得(MySQL) SELECT name, CHAR_LENGTH(name) AS with_spaces, CHAR_LENGTH(TRIM(name)) AS without_spaces FROM employees;
TRIM関数の詳しい使い方は「TRIM関数で文字列から空白や指定した文字を取り除く方法」をご覧ください。
LENGTH – REPLACE: 特定文字の出現回数をカウント
-- カンマの数を数える = CSVフィールドの項目数を推定(MySQL) SELECT csv_data, CHAR_LENGTH(csv_data) - CHAR_LENGTH(REPLACE(csv_data, ',', '')) AS comma_count FROM import_data; -- 応用: カンマが3つ以上のレコードを検出 SELECT * FROM import_data WHERE CHAR_LENGTH(csv_data) - CHAR_LENGTH(REPLACE(csv_data, ',', '')) >= 3;
✅ テクニック解説: LENGTH(str) - LENGTH(REPLACE(str, '検索文字', '')) は、検索文字を空文字に置換した際の文字数差分から出現回数を算出するイディオムです。REPLACE関数の詳しい使い方はこちら。
SUBSTR + LENGTH: 末尾N文字を取得
-- ファイル名の拡張子(末尾4文字)を取得(Oracle) SELECT file_name, SUBSTR(file_name, LENGTH(file_name) - 3) AS extension FROM documents; -- MySQL の場合: SUBSTRING + CHAR_LENGTH または RIGHT 関数 SELECT file_name, SUBSTRING(file_name, CHAR_LENGTH(file_name) - 3) AS extension, RIGHT(file_name, 4) AS extension2 FROM documents;
SUBSTR関数の詳しい使い方は「SUBSTR関数で文字列の一部を切り出す方法」をご覧ください。
NULLと空文字の扱い
LENGTH関数にNULLや空文字を渡したときの挙動はRDBMSによって異なります。
-- NULLを含むカラムの安全な文字数チェック(MySQL) SELECT name, COALESCE(CHAR_LENGTH(name), 0) AS safe_length FROM employees; -- Oracle: 空文字もNULLも考慮した安全なチェック SELECT name, NVL(LENGTH(name), 0) AS safe_length FROM employees;
パフォーマンスの注意点
-- MySQL 5.7以降: Generated Column でインデックスを活用 ALTER TABLE products ADD COLUMN name_length INT GENERATED ALWAYS AS (CHAR_LENGTH(product_name)) STORED; CREATE INDEX idx_name_length ON products(name_length); -- インデックスが効くようになる SELECT * FROM products WHERE name_length >= 20;
よくあるトラブルと対処法
関連する記事
まとめ
LENGTH関数はシンプルに見えて、RDBMSごとの挙動の違いやマルチバイト文字の扱いなど注意点が多い関数です。特にMySQLを使う場合は「文字数が欲しいならCHAR_LENGTH()」「バイト数が欲しいならLENGTH()」と覚えておくだけで、多くのトラブルを防げます。WHERE句でのデータ品質チェックやCASE文での分類など、実務でも活用範囲が広いので、ぜひ使いこなしてください。

