concat()関数と||(2つのパイプ)を使った連結では動作が異なります
concat()関数での連結ではNULLが混在した場合NULLを無視しますが、||(パイプ)での連結では1つでもNULLが混じると連結結果もNULLになります。参考までにですが、Oracleではconcat()関数でもパイプを使った連結においてもNULLは無視した動作になります。PostgreSQLのパイプによる連結の動作は注意が必要です。もう一つ見落としがちな注意点として、concat()関数を使いNULLだけの連結を行っても結果はNULLにはならず、空文字になります。またconcat()関数は生成列での採用はできません。生成列ではパイプで代用するしかありません。
動作検証
# 検証用データの確認
#
myposdb=# \pset null '(null)'
Null display is "(null)".
myposdb=# select * from ex1 order by 1;
lno | first_name | last_name
-----+------------+-----------
1 | 拓朗 | 西山
2 | (null) | 東川
3 | 優美 | (null)
4 | (null) | (null)
(4 rows)
# concat()関数による連結はいかなる場合も連結結果がnullになる事はありません
#
myposdb=# select lno,concat(first_name,last_name) as full_name from ex1 order by 1;
lno | full_name
-----+-----------
1 | 拓朗西山
2 | 東川
3 | 優美
4 | <--- nullだけの連結でもnullにはなりません(注1)
(4 rows)
(注1) Oracleでもlno 1~3までは同じ結果になりますが、Oracleではnull同士の連結はnullになります。
# パイプによる連結はNULLが含まれる場合結果はNULLになります。
#
myposdb=# select lno,first_name||last_name as full_name from ex1 order by 1;
lno | full_name
-----+-----------
1 | 拓朗西山
2 | (null)
3 | (null)
4 | (null)
(4 rows)
myposdb=#
concat_ws関数を使った連結
PostgreSQLにはconcat()関数のさらに進化版と言えるconcat_ws()がありますので、こちらの動作も検証します。
# concat_ws()関数は、第一引数に指定する文字で、後続に続くパラメータ値を連結します。
# 以下の通り基本的にconcat()関数の動きと同じです。
#
myposdb=# select lno,concat_ws('-',first_name,last_name) as full_name from ex1 order by 1;
lno | full_name
-----+-----------
1 | 拓朗-西山
2 | 東川 <- 連結対象が存在しない場合区切り文字も省略されます。
3 | 優美
4 |
(4 rows)
myposdb=#
Oracleと比較し便利と感じた事
postgreSQLのconcat()関数はOracleと違い、一度に複数の文字列を連結できる点とても便利です。またconcat_ws()関数は、csv区切りで出力するようなシーンではとても重宝します。
検証用データ
以下今回の検証用データです。
create table ex1 (
lno integer,
first_name varchar(20),
last_name varchar(20)
);
insert into ex1(lno,first_name,last_name) values(1,'拓朗','西山');
insert into ex1(lno,first_name,last_name) values(2,null,'東川');
insert into ex1(lno,first_name,last_name) values(3,'優美',null);
insert into ex1(lno,first_name,last_name) values(4,null,null);