はじめに
みなさんはダブルパイプで困ったことがありますか?
私はTryHackMeでマシン攻略をしていた時、「パイプによるORのバイパスはできない」と思い込み、途方もない時間を無駄にしたことがあります。
そうならないためにも、各SQLのダブルパイプの挙動についてまとめます。
標準SQLではどう決まっているのか
標準SQLとは?
ANSIが最初に策定し、現在ではISO(国際標準化機構)がISO-9075として標準化した規格。
データベース言語はだいたいこんな感じにしようねというの共通ルールみたいなもの。
標準SQLでは || は連結演算子としてあらわされています。
<concatenation operator> ::= ||
これはISOとなった1992年のSQL-92には明記されていました。
https://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt
ということは大体の言語では || は文字列の連結に使われるはずです。
DBMS別で見ていく
PostgreSQL
PostgreSQLにおいてダブルパイプは連結演算子として扱われます。
text || text → text
'Post' || 'greSQL' → PostgreSQL
また、いい感じに型を揃えてくれる機能もあります。
text || anynonarray → text
anynonarray || text → text
'Value: ' || 42 → Value: 42
注意点として、NULL を使った結合は結果が NULL になります。 NULLを含めて結合したい場合は CONCAT 関数を使う必要があります(CONCAT 関数はNULLを無視して結合してくれます)。
'Data' || NULL → NULL
concat('Data', NULL) → 'Data'
Oracle Database
Oracleも標準に従い、ダブルパイプは連結演算子として機能します。
'Ora' || 'cle' → 'Oracle'
Oracleでは空文字と NULL は同じものとみなされる仕様があります。
そのため、PostgreSQLとは異なり、NULL と結合しても結果は NULL になりません。
'Data' || NULL → 'Data'
Concatenation Operator | Oracle Database SQL Language Reference
MySQL / MariaDB
MySQLにおいて、ダブルパイプはプログラミング言語のように論理和(OR)として扱われます。
ちなみに && は and として扱われます。
文字列を結合しようとして || を使うと、文字列は数値の 0 に変換され、0 OR 0 の判定が行われるため、謎の 0 が返ってきます。
'My' || 'SQL' → 0
これを標準SQLと同じ「文字列結合」として扱いたい場合は、sql_mode の設定を変更する必要があります。
SET sql_mode='PIPES_AS_CONCAT';
'My' || 'SQL' → 'MySQL'
あるいは、大人しく CONCAT 関数を使うのが無難です。
ただし、公式リファレンスにはこのような記述があります。
The ||, operator is a nonstandard extension, and is deprecated; expect support for it to be removed in a future version of MySQL.
非標準の拡張機能だから、将来のバージョンで削除する。
とあるので将来的には連結演算子として置き換えたいようです。
Logical Operators | MySQL 8.4 Reference Manual
SQL Server (MSSQL)
長らく + しか使えませんでしたが、SQL Server 2022 (16.x) および Azure SQL Database から、標準準拠の || がサポートされました。
-- SQL Server 2022以降 / Azure SQL
'SQL' || 'Server' → 'SQLServer'
それより前のバージョン(2019以前)では || は構文エラーになります。 古い環境ではプラス記号 + または CONCAT 関数を使用する必要があるようです。
-- SQL Server 2019以前
'SQL' + 'Server' → 'SQLServer'
ちなみに、新しく追加された || 演算子は標準SQL準拠の挙動となるため、片方が NULL だと結果も NULL になります( CONCAT 関数とは挙動が違うので注意)。
+ (String Concatenation) | Microsoft Learn
|| (String concatenation) (Transact-SQL)
SQLite
SQLiteは、標準SQLにしたがった挙動をしています。
連結演算子として機能しますが、NULLの扱いも標準通り厳格です。
'SQ' || 'Lite' → 'SQLite'
PostgreSQLと同様、片方がNULLの場合は結果もNULLになります。
Oracleのような優しさ(?)はありません。
'Data' || NULL → NULL
SQL As Understood By SQLite | Operators
まとめ
| DBMS | || の挙動 | NULLとの結合 ('A' || NULL) | 推奨/代替関数 |
|---|---|---|---|
| Standard SQL | 文字列結合 | NULL | - |
| PostgreSQL | 文字列結合 | NULL | CONCAT() もあるが || が主流? |
| Oracle | 文字列結合 | 'A' (空文字扱い) | CONCAT() |
| MySQL | 論理OR (※1) | 1 または 0 | CONCAT() (※1 設定で変更可能、将来的になくなる) |
| SQL Server | エラー (古い版) 文字列結合 (2022以降) |
バージョンによる | + または CONCAT() |
| SQLite | 文字列結合 | NULL | - |