202


42

Oracle 9iが空の文字列をNULLとして扱うのはなぜですか?

私はそれを「NULL」と見なすことを「知っています」と言っていますが、それが「事実」と言っても意味がありません。 私がSQLの仕様を理解しているように、 ''は 'NULL’と同じではありません - 一つは有効なデータであり、もう一つは同じ情報がないことを示しています。

推測しても構いませんが、そうであるかどうかを示してください。 それについてコメントすることができるOracleの誰かがいるなら、それは素晴らしいことです!

10 Answer


208


その答えは、Oracleは非常に古くからあるということです。

SQL標準がある前の昔、Oracleは VARCHAR /` VARCHAR2`カラムの空の文字列は `NULL`であり、NULLの意味は1つしかない(区別するための関係理論がある)という設計上の決定をしました。入力を求められたことがないデータ、回答は存在するがユーザーには認識されていないデータ、回答がないデータなど これらはすべて、何らかの意味の「NULL」を構成します。

SQL標準が登場し、「NULL」と空の文字列が異なるエンティティであることに同意するまでに、この2つが同等であると想定したコードを持つOracleユーザーはすでに存在していました。 そのため、オラクルは基本的に、既存のコードを破る、SQL標準に違反する、または潜在的に多数のクエリの機能を変更するようなある種の初期化パラメータを導入するという選択肢を残しました。 SQL標準(IMHO)に違反することは、これら3つの選択肢の中で最も混乱をきたさないものでした。

Oracleは将来のリリースで標準SQLに準拠するためにVARCHARデータ型が変更される可能性を残しています(Oracleではそのデータ型の振る舞いは今後も変わらないことが保証されているため) 。


56


http://asktom.oracle.com/pls/asktom/f?p=100:11:0

P11_QUESTION_ID:5984520277372 [Tom Kyte] Oracleの副社長:

_ _ ゼロ長のvarcharはNULLとして扱われます。

''はNULLとして扱われません。

char(1)に代入されたときの ''は ''になります(char型は空白の埋め込み文字列です)。

'' varchar2(1)に割り当てられると ''になります ''これは長さ0の文字列であり、長さ0の文字列はOracleではNULLです(長すぎません '') _ _


18


Oracleを以前の開発者がおそらく考えていたような方法、つまりデータ入力システムのバックエンドとして考えるとすれば、これはもっと理にかなっていると思います。 データベース内のすべてのフィールドは、データ入力オペレーターが自分の画面に表示した形式のフィールドに対応していました。 オペレータがフィールドに何も入力しなかった場合、それが「誕生日」でも「住所」でも、そのフィールドのデータは「不明」です。 誰かのアドレスが本当に空の文字列であることをオペレータが示すことはできません。それはとにかくあまり意味がありません。


17


Oracleのドキュメントは、少なくともバージョン7までさかのぼって、開発者にこの問題を警告しています。

OracleはNULLSを「不可能な値」の手法で表現することを選択しました。 たとえば、数値位置にNULLが含まれていると、 "マイナスゼロ"という不可能な値として格納されます。 計算の結果生じるマイナスのゼロは、格納される前にプラスのゼロに変換されます。

Oracleはまた、誤って、長さゼロのVARCHAR文字列(空の文字列)を不可能な値と見なし、NULLを表すのに適した選択と見なしました。 空の文字列は不可能な値からかけ離れていることがわかります。 文字列連結の操作のもとでのアイデンティティでさえあります。

Oracleのドキュメントでは、データベース設計者および開発者に対して、将来のバージョンのOracleでは、空の文字列とNULLとの関連付けが解除され、その関連付けに依存するコードが破損する可能性があることが警告されています。

不可能な値以外にNULLにフラグを付ける方法がありますが、Oracleはそれらを使用しませんでした。

(私は、行と列が交差することを意味するために上記の「場所」という言葉を使っています。)


2


空の文字列がNULLと同じであるのは、その2つ(空の文字列とnull)が同じでない場合と比較したときの「悪しさ」が単純だからです。

NULLと空の文字列が同じではない言語では、常に両方の条件をチェックする必要があります。


0


_ Oracle Databaseは現在、長さがゼロの文字値をNULLとして扱います。 ただし、将来のリリースではこれが当てはまるとは限りません。空の文字列をNULLと同じように扱わないでください。 _

考えられる理由

  1. 'val IS NOT NULL’は 'val!=' 'より読みやすくなります。

  2. 両方の条件 `val!= ''とval IS NOT NULL`をチェックする必要はありません。


0


本からの例

serveroutputをonに設定します。 DECLARE empty_varchar2 VARCHAR2(10):= ''; empty_char CHAR(10):= ''; DBMS_OUTPUT.PUT_LINE( 'empty_varchar2がNULL')である場合は、empty_varchar2がNULLの場合。 END IF;

DBMS_OUTPUT.PUT_LINE( '' '' 'がNULLの場合)NULL。 END IF;

DBMS_OUTPUT.PUT_LINE( 'empty_charがNULL')の場合は、empty_charがNULLです。 DBMS_OUTPUT.PUT_LINE( 'empty_charがNOT NULL')の場合、ELSIF empty_charはNULLではありません。 END IF;

終わり;


-1


NULLとして扱わないことも特に役に立ちません。

Oracleのこの領域を間違えた場合、通常すぐに気付くでしょう。 しかしSQLサーバでは、それはうまくいくように見え、問題は誰かがNULLの代わりに空の文字列を入力したときにのみ現れます(おそらく.netクライアントライブラリから。nullは ""とは異なりますが、通常は同じです) )

Oracleが正しいと言っているわけではありませんが、どちらの方法もほぼ同じくらい悪いと思われます。


-6


確かに、私はOracleに対処することに何の困難もありませんでした。明らかにデータベースに挿入することが許可されている無効なdatetime値(DUMP()関数で見ただけでは表示できません)バイナリ列としてクライアントのいくつかのバグのあるバージョン! データベースの保全性を保護するために

OracleのNULLリンク処理:


-6


まず第一に、nullとnull文字列は常にOracleによって同じものとして扱われていませんでした。 null文字列は、定義により、文字を含まない文字列です。 これはnullとまったく同じではありません。 NULLは、定義上、データが存在しないことを意味します。

5〜6年ほど前、Oracleではnull文字列はnullとは異なる方法で扱われていました。 nullのように、null文字列はすべてと等しく、すべてと異なっていましたが(nullの場合は問題ありませんが、null文字列の場合はまったく間違っています)、少なくともlength(null string)は0を返します。長さゼロの文字列

現在のOracleでは、length(null)は私が推測しているnullを返しますが、length(null string)もnullを返します。これはまったく間違っています。

私は、なぜ彼らがこれら2つの異なる「値」を同じように扱おうと決めたのか理解していません。 それらは異なることを意味し、プログラマーは異なる方法でそれぞれに作用する能力を持つべきです。 彼らが彼らの方法論を変えたという事実は彼らが本当にこれらの値がどのように扱われるべきであるかについて手がかりを持っていないことを私に言います。