「Oracleでは長さが0(ゼロ)の文字値をNULLとして処理されるが、将来変更される可能性がある」というマニュアルの記載はいつから？

# はじめに

以前からOracleでは空文字がNULLと判定されています。
他のデータベースとは違う動作となるので、データベース移行の際は問題というか注意点の一つになることが多いです。

とあるサイトで議論した際、最近のマニュアル（[19c SQLリファレンスガイド](https://docs.oracle.com/cd/F19136_01/sqlrf/Nulls.html#GUID-B0BA4751-9D88-426A-84AD-BCDBD5584071)）では以下のような記載があるよ、と教えてもらいました。
```
ノート:Oracle Databaseは現在、長さが0(ゼロ)の文字値をNULLとして処理します。
ただし、将来のリリースではこの処理が変更される場合があるため、空の文字列をnullと同じように処理しないことをお薦めします。
```

いつから記載されているのか気になったため、さかのぼってみてみたらだいぶ古くから同じような記載になっていたので、記録しておきます。
なお、最後尾に Oracleの空文字とNULLの挙動についてはOracle Live SQLでの確認結果を載せておいたので気になる方は確認してみてください。

- [SQL言語リファレンス 21c](https://docs.oracle.com/cd/F39414_01/sqlrf/Nulls.html#GUID-B0BA4751-9D88-426A-84AD-BCDBD5584071)
- [SQL言語リファレンス 20c](https://docs.oracle.com/cd/F32587_01/sqlrf/Nulls.html#GUID-B0BA4751-9D88-426A-84AD-BCDBD5584071)
- [SQL言語リファレンス 19c](https://docs.oracle.com/cd/F19136_01/sqlrf/Nulls.html#GUID-B0BA4751-9D88-426A-84AD-BCDBD5584071)
- [SQL言語リファレンス 18c](https://docs.oracle.com/cd/E96517_01/sqlrf/Nulls.html#GUID-B0BA4751-9D88-426A-84AD-BCDBD5584071)
- [SQL言語リファレンス 12c リリース2 (12.2)](https://docs.oracle.com/cd/E82638_01/sqlrf/Nulls.html#GUID-B0BA4751-9D88-426A-84AD-BCDBD5584071)
```
ノート:Oracle Databaseは現在、長さが0(ゼロ)の文字値をNULLとして処理します。
ただし、将来のリリースではこの処理が変更される場合があるため、空の文字列をnullと同じように処理しないことをお薦めします。
```

- [SQL言語リファレンス 12cリリース1 (12.1)](https://docs.oracle.com/cd/E57425_01/121/SQLRF/sql_elements005.htm#i59110)
- [SQL言語リファレンス 11gリリース2 (11.2)](https://docs.oracle.com/cd/E16338_01/server.112/b56299/sql_elements005.htm#i59110)
- [SQL言語リファレンス 11g リリース1(11.1)](https://docs.oracle.com/cd/F25597_01/document/products/oracle11g/111/doc_dvd/server.111/E05750-03/sql_elements.htm#47987)
```
注意:
Oracle Databaseは現在、長さが0(ゼロ)の文字値をNULLとして処理します。
ただし、この処理はOracleの今後のバージョンでも継続されるとはかぎらないため、空の文字列をNULLとして処理しないことをお薦めします。
```


※ Oracle10gの日本語版のSQLリファレンスは見つけられませんでした
- [Oracle9i SQL リファレンス リリース 2（9.2）](https://docs.oracle.com/cd/F25597_01/document/oracle9i/920/generic/server/J06261-02.pdf)
- [Oracle9i SQLリファレンス, リリース1（9.0.1）](https://docs.oracle.com/cd/F25597_01/document/products/database/oracle9i/901/generic/server/J04117-01.pdf)
```
現在、Oracle は、長さが 0（ゼロ）の文字値を NULL として処理します。
ただし、この処理は Oracle の今後のバージョンでも継続されるとはかぎらないため、空の文字列を NULL として処理しないことをお薦めします。
```

- [Oracle8i SQLリファレンス Vol.1, リリース8.1](https://docs.oracle.com/cd/F25597_01/document/products/iserver/oracle8i/817/generic/basic/J02326-01.pdf)
- [Oracle8 Server SQL リファレンス: Vol.1 リリース 8.0](https://docs.oracle.com/cd/F25597_01/document/products/iserver/oracle8/80/generic/a56823-1.pdf)
```
（現在、Oracle は、長さが 0（ゼロ）の文字値を NULL として処理します。
ただし、この処理は Oracle の将来のバージョンでも継続されるとは限らないため、空の文字列を NULL として処理しないことをお薦めします。）
```

- [Oracle7 Server SQL Reference Release 7.3](https://docs.oracle.com/pdf/A32538_1.pdf)
日本語版のマニュアルは見つけられませんでした。
```
Oracle7 currently treats a character value with a length of zero as null.
However, this may not continue to be true in future versions of Oracle7.
```

# まとめ
少なくともOracle7の時代から、他のデータベースとは違う挙動となっており、注意が必要、という喚起はされていました。
現時点でも挙動が変わっていないということは、きっと永遠に変わらないのでしょう。
Oracle6やそれ以前のマニュアルの記載をご存じの方がいらっしゃったら是非お知らせください。

### Oracleにおける空文字とNULLの扱い

その前に、空文字とNULLについて、改めて振り返っておきます。

[Oracle Live SQL](https://livesql.oracle.com/apex/f?p=590:1000) で実行可能です。
テストテーブルを作成し、'' 空文字 と NULL を挿入します。

<details><summary>テストテーブル作成とテストデータ挿入</summary>

```:テストテーブル作成・テストデータ挿入
drop table test01;
create table test01(
　　id number primary key,
　　testc char(8),testnc nchar(8),testvc varchar2(8),testnvc nvarchar2(8));
insert into test01 values (1,'','','','');
insert into test01 values (2,null,null,null,null);
commit;
```
</details>

テーブルの中身を見てみると、NULLとして挿入されていることがわかります。
```
select * from test01;
```
|ID |TESTC |TESTNC |TESTVC | TESTNVC | 
|-|-|-|-|-|
|1|-|-|-|-|
|2|-|-|-|-| 

DUMPコマンドでも確認しておきます。
```
select id,dump(testc, 16),dump(testnc, 16),dump(testvc, 16),ump(testnvc, 16) from test01;
```
|ID |DUMP(TESTC,16) |DUMP(TESTNC,16) |DUMP(TESTVC,16) |DUMP(TESTNVC,16) | 
|-|-|-|-|-|
|1|NULL|NULL|NULL|NULL|
|2|NULL|NULL|NULL|NULL|

以下のSQLはいずれも同じ結果で、両方の行が出力されます。

```:IS NULLでのSELECT
select * from test01 where testc is null;
select * from test01 where testnc is null;
select * from test01 where testvc is null;
select * from test01 where testnvc is null;
```
|ID |TESTC |TESTNC |TESTVC | TESTNVC | 
|-|-|-|-|-|
|1|-|-|-|-|
|2|-|-|-|-| 

こちらはいずれもデータが出力されません。

```:空文字でのSELECT
select * from test01 where testc = '';
select * from test01 where testnc = '';
select * from test01 where testvc = '';
select * from test01 where testnvc = '';
```

```
no data found
```

また、NOT NULL制約を付した行には空文字を挿入することはできません。
```:NOT NULL制約の追加
truncate table test01;
ALTER TABLE test01 MODIFY (testc NOT NULL);
insert into test01 values (1,'','','','');
```
```
ORA-01400: cannot insert NULL into ("SQL_XXXXXXXXXXXXXXXX"."TEST01"."TESTC")
ORA-06512: at "SYS.DBMS_SQL", line 1721
```

#### 参考
- [Oracle では文字長 0 の文字型カラム値は勝手に NULL になってしまう!?](http://blog.livedoor.jp/i_am_best/archives/7870002.html)