コマンド道場

$ man concat

CONCAT / ||

文字列関数

文字列をつなぐ。|| は NULL が混じると全体が NULL、CONCAT は NULL を飛ばす。

呼び出しの形

文字列 || 文字列
CONCAT(値, 値, ...)
CONCAT_WS(区切り, 値, ...)

つまずきやすいところ

  • || は NULL が 1 つでも混じると全体が NULL です。画面から項目がまるごと消えるので、気づきにくい不具合になります。

  • MySQL・MariaDB の既定の設定では || は論理 OR です。文字列をつなぐつもりで書いても、エラーにならずに 0 や 1 が返ります(PIPES_AS_CONCAT を有効にしたときだけ連結)。移植する SQL では CONCAT を使います。

  • CONCAT は標準 SQL の関数ではなく、製品ごとに挙動が違います。Oracle の CONCAT は引数を 2 つしか取りません。

  • 数値を混ぜてつなぐと、暗黙の型変換が働く製品と、エラーになる製品があります。明示的に文字列へ変換しておくほうが安全です。

実行例

結果は実際に流したものです。同じ SQL を 自由に打てる画面 で試すと、同じ結果になります。

|| と CONCAT の違いを並べて見る
SELECT kokyaku_name, pref, kokyaku_name || ' / ' || pref AS pipe, CONCAT(kokyaku_name, ' / ', pref) AS concat_fn FROM kokyaku ORDER BY kokyaku_id
kokyaku_nameprefpipeconcat_fn
青葉工業東京都青葉工業 / 東京都青葉工業 / 東京都
白樺物産大阪府白樺物産 / 大阪府白樺物産 / 大阪府
黒松システム東京都黒松システム / 東京都黒松システム / 東京都
赤坂商会NULLNULL赤坂商会 /
三田商事愛知県三田商事 / 愛知県三田商事 / 愛知県

5 行

pref が NULL の顧客では、|| の結果だけが NULL になります。

CONCAT_WS と COALESCE で埋める書き方
SELECT kokyaku_name, CONCAT_WS(' / ', kokyaku_name, pref) AS ws, kokyaku_name || ' / ' || COALESCE(pref, '未登録') AS uzume FROM kokyaku ORDER BY kokyaku_id
kokyaku_namewsuzume
青葉工業青葉工業 / 東京都青葉工業 / 東京都
白樺物産白樺物産 / 大阪府白樺物産 / 大阪府
黒松システム黒松システム / 東京都黒松システム / 東京都
赤坂商会赤坂商会赤坂商会 / 未登録
三田商事三田商事 / 愛知県三田商事 / 愛知県

5 行

説明

文字列をつなぐ書き方は 2 通りあり、NULL の扱いがまるで違います。

  • || … 標準 SQL の連結演算子。片方でも NULL なら結果は NULL
  • CONCAT(...) … 関数。NULL は空文字として飛ばします

住所や氏名のように「一部が未入力かもしれない」ものをつなぐときは、この差が効きます。|| を使うなら COALESCE で埋めるのが定石です。

区切り文字を挟みたいときは CONCAT_WS(with separator)が便利です。こちらも NULL の項目は飛ばすので、区切りだけが残ることがありません。

ほかの製品でも通るか

この書き方が使えない製品があります そのまま使える: PostgreSQL / SQLite / Oracle Database / IBM Db2

  • MySQL ではエラーにならずに結果が変わります(|| による文字列連結)
  • MariaDB ではエラーにならずに結果が変わります(|| による文字列連結)
  • SQL Server では使えません(|| による文字列連結)

製品ごとの対応表(根拠つき)を見る

次に読む

根拠にした一次情報