コマンド道場

$ man concat

CONCAT / ||

文字列関数

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

呼び出しの形

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

つまずきやすいところ

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

  • 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 / MySQL / MariaDB / SQLite / Oracle Database / IBM Db2

  • SQL Server では使えません|| による文字列連結

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

次に読む

根拠にした一次情報