' ' を と見なすことは知っていますが、なぜそうなNULL
のかはあまりわかりません。私が SQL 仕様を理解しているように、' ' は同じではありません-- 1 つは有効なデータであり、もう 1 つは同じ情報がないことを示しています。NULL
勝手な推測ですが、もしそうなら教えてください。それについてコメントできるオラクルの誰かがいるなら、それは素晴らしいことです!
答えは、Oracleは非常に古いということだと思います。
SQL標準が存在する前の昔、Oracleは、VARCHAR
/VARCHAR2
列の空の文字列がNULL
あり、NULLの意味が1つしかないという設計上の決定を下しました(プロンプトが表示されたことのないデータを区別するリレーショナル理論家がいます。答えはあるがユーザーにはわからないデータ、答えがないデータなど、いずれも何らかの感覚を構成しますNULL
)。
SQL標準が登場しNULL
、空の文字列が別個のエンティティであることに同意するまでに、2つが同等であると想定するコードを持っているOracleユーザーがすでに存在していました。そのため、Oracleには基本的に、既存のコードを壊したり、SQL標準に違反したり、潜在的に多数のクエリの機能を変更するような初期化パラメータを導入したりするオプションが残されていました。SQL標準(IMHO)に違反することは、これら3つのオプションの中で最も混乱が少ないものでした。
OracleはVARCHAR
、SQL標準に準拠するために将来のリリースでデータ型が変更される可能性を残しています(VARCHAR2
そのデータ型の動作は今後も同じであることが保証されているため、Oracleで誰もが使用する理由です)。
オラクルのトム・カイト副社長:
長さがゼロのvarcharはNULLとして扱われます。
''はNULLとして扱われません。
'' char(1)に割り当てられると、''になります(charタイプは空白の埋め込み文字列です)。
'' varchar2(1)に割り当てられると、''になります。これは、長さがゼロの文字列であり、Oracleでは長さがゼロの文字列がNULLです(長くはありません'')
Oracle のドキュメントは、少なくともバージョン 7 までさかのぼって、開発者にこの問題を警告しています。
Oracle は、「不可能な値」手法によって NULLS を表現することを選択しました。たとえば、数値の場所にある NULL は、「マイナス ゼロ」というありえない値として格納されます。計算結果のマイナス ゼロは、格納される前にプラス ゼロに変換されます。
Oracle はまた、誤って、長さ 0 の VARCHAR 文字列 (空の文字列) を不可能な値であると見なし、NULL を表す適切な選択を選択しました。空の文字列は不可能な値とはほど遠いことがわかります。文字列連結の操作下の同一性ですらあります!
Oracle のドキュメントでは、Oracle の将来のバージョンによっては、空の文字列と NULL の間のこの関連付けが壊れ、その関連付けに依存するすべてのコードが壊れる可能性があることを、データベースの設計者と開発者に警告しています。
不可能な値以外の NULLS にフラグを立てる手法はありますが、Oracle はそれらを使用しませんでした。
(上記の「場所」という言葉は、行と列の交点を意味するために使用しています。)
以前の開発者がおそらくそうしていたように Oracle を考えれば、これはもっと理にかなっていると思います。データベースのすべてのフィールドは、データ入力オペレーターが画面に表示したフォームのフィールドに対応していました。オペレーターが「生年月日」であろうと「住所」であろうと、フィールドに何も入力しなかった場合、そのフィールドのデータは「不明」です。オペレーターが誰かのアドレスが本当に空の文字列であることを示す方法はなく、とにかくあまり意味がありません。
本からの例
set serveroutput on;
DECLARE
empty_varchar2 VARCHAR2(10) := '';
empty_char CHAR(10) := '';
BEGIN
IF empty_varchar2 IS NULL THEN
DBMS_OUTPUT.PUT_LINE('empty_varchar2 is NULL');
END IF;
IF '' IS NULL THEN
DBMS_OUTPUT.PUT_LINE(''''' is NULL');
END IF;
IF empty_char IS NULL THEN
DBMS_OUTPUT.PUT_LINE('empty_char is NULL');
ELSIF empty_char IS NOT NULL THEN
DBMS_OUTPUT.PUT_LINE('empty_char is NOT NULL');
END IF;
END;
NULL として扱わないことも特に役に立たないからです。
Oracle のこの領域で間違いを犯した場合、通常はすぐに気付きます。ただし、SQLサーバーでは機能しているように見え、誰かがNULLの代わりに空の文字列を入力した場合にのみ問題が発生します(おそらく.netクライアントライブラリから、nullは ""とは異なりますが、通常は同じように扱います)。
オラクルが正しいと言っているわけではありませんが、どちらの方法もほぼ同じように悪いように思えます。
まず第一に、nullとnull文字列はOracleによって常に同じものとして扱われるとは限りませんでした。ヌル文字列は、定義上、文字を含まない文字列です。これはnullとはまったく同じではありません。NULLは、定義上、データがないことを意味します。
5、6年ほど前、Oracleはnull文字列をnullとは異なる方法で処理していました。nullと同様に、null文字列はすべてに等しく、すべてとは異なります(nullの場合は問題ないと思いますが、null文字列の場合は完全に間違っています)が、null文字列は長さがゼロの文字列。
現在Oracleでは、length(null)はnullを返しますが、これは問題ないと思いますが、length(null string)もnullを返します。これは完全に間違っています。
なぜ彼らがこれらの2つの異なる「価値」を同じように扱い始めることにしたのか理解できません。それらは異なることを意味し、プログラマーは異なる方法でそれぞれに作用する能力を持っている必要があります。彼らが方法論を変更したという事実は、これらの値がどのように扱われるべきかについての手がかりを本当に持っていないことを私に教えてくれます。
確かに、データベースへの挿入が許可されている無効な日時値(印刷、変換など、DUMP()関数で確認することはできません)など、Oracleの処理に問題がありました。バイナリ列としてのクライアントのバージョン!データベースの整合性を保護するためにこれだけです!
NULLリンクのOracle処理:
http://digitalbush.com/2007/10/27/oracle-9i-null-behavior/
http://jeffkemponoracle.com/2006/02/empty-string-andor-null.html