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


216

私はそれ ''をと見なしていることを知っていNULLますがこれが事実である理由を私に伝えることはあまりありません。SQL仕様を理解しているように、 ''は同じではありませんNULL-1つは有効なデータムであり、もう1つは同じ情報がないことを示しています。

遠慮なく推測してください。その場合はそれを示してください。Oracleからコメントできる人がいたら、それは素晴らしいことです。


9
遠慮なく推測してください。どういうわけか私はそれがあなたに最高の答えのセットを提供するとは思わない..
SCdF '15

1
私はそうではないと思いますが、この件について確信があるかどうか確信が持てなかったので、私はドアを開けるつもりだと考えました。これまでのところ、問題なく機能しているようです。
Chris R


回答:


216

答えは、Oracleは非常に古いということです。

SQL標準が存在する前の昔、OracleはVARCHAR/ VARCHAR2列に空の文字列がNULLあり、NULLの感覚が1つだけであるという設計上の決定をしました(要求されたことのないデータを区別する関係理論家がいます)。回答はあるがユーザーには分からないデータ、回答がないデータなど、いずれもある程度の感覚を構成しNULLます。

SQL標準が登場しNULL、空の文字列が別個のエンティティであることに同意した時点で、Oracleユーザーは、2つが同等であると想定したコードをすでに持っていました。したがって、Oracleは基本的に、既存のコードを壊す、SQL標準に違反する、または潜在的に多数のクエリの機能を変更するようなある種の初期化パラメーターを導入するという選択肢を残していました。SQL標準(IMHO)への違反は、これらの3つのオプションの中断が最も少ないものでした。

OracleはVARCHAR、SQL規格に準拠するために将来のリリースでデータ型が変更される可能性を残しています(そのVARCHAR2ため、そのデータ型の動作は今後も同じであることが保証されているため、誰もがOracleで使用します)。


60

オラクルのトム・カイト副社長:

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

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

''は、char(1)に割り当てられると ''になります(char型は空白が埋め込まれた文字列です)。

'' varchar2(1)に割り当てられた場合、 ''は長さ0の文字列であり、長さ0の文字列はOracleではNULLです(長くはありません '')


17
うわー、トムはかなり卑劣です。質問がSQL92からのひどい相違に関連していることを考えると、彼はそれについてあまりパンチのない人だと思うでしょう...彼は答えるのに疲れているかもしれませんが。
Chris R

8
トムについての最もよい事はあなたが明確な答えを得るということです、そしてそれは彼の考えを正確に述べます。テキストを使用したコメントのいくつかを探して、Ask Tom
Chris Gillに

9
ただし、2行目が''
ypercubeᵀᴹ

2
@ypercube引用は、トムが実際に使用する単語を変更しても正確にはなりません。トムが紛らわしく言ったと思うなら、うーん。多分。私は彼がにスポットを当てていると思います。がVARCHAR2 ''暗黙的に変換されるときに最も混乱する状況が発生します。たとえばcast('' as char(1)) is null
sehe

1
@sehe私にとって混乱するビットは、デュアルから1を選択することです( ''はnull)
マットフリーク

20

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


5
これは、データ入力システムのすべてのフィールドが必須であると想定している場合にのみ意味があります。必須ではないフィールドへの非回答(「犬の名前」など)は有効であるため、空の文字列にはNULLとは異なる目的があります。この前提が整っていても、初期の開発者がOracleを「データ入力システムの栄光のあるバックエンド」だと思っていたのではないかと思います。
Jared

19

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

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

Oracleはまた、誤って、長さがゼロのVARCHAR文字列(空の文字列)を不可能な値と見なし、NULLを表すための適切な選択を選択しました。空の文字列は不可能な値にはほど遠いことがわかります。文字列の連結のもとでのアイデンティティです!

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

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

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


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


2

空の文字列はNULLと同じです。これは、2つ(空の文字列とnull)が同じではない状況と比較すると、「より小さな悪」だからです。

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


not null列に制約を設定し、空の文字列のみをチェックします。
Egor Skriptunoff 2013年

6
WHERE Field <> ''空の文字列に対するANSI動作のデータベースでは、両方の条件のチェックは簡単です。フィールドがNULLでも空でもない場合にのみtrueを返します。

1

公式の11gドキュメントによると

Oracle Databaseは現在、長さがゼロの文字値をNULLとして扱います。ただし、これは今後のリリースでは当てはまらない可能性があるため、空の文字列をnullと同じように処理しないことをお勧めします。

考えられる理由

  1. val IS NOT NULL より読みやすい val != ''
  2. 両方の条件を確認する必要はありません val != '' and val IS NOT NULL

5
完全にANSI準拠のデータベースでは、両方の条件を確認する必要はありません。val <> ''はすでに除外されていますNULL。たぶん、あなたが意味したval = '' OR val IS NULL。ただし、NULLとして比較されない空の文字列は便利です
ErikE 2016

比較部分に同意します。
ソーター

0

本の例

   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;

-1

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

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

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


2
はるかに簡単にデバッグできます。また、画面に空のセルまたは入力が表示される場合は、DBのデータがnullであることがわかります。'' <> NULLである他のDBでは、データがnullまたは ''であるかどうかを「見る」ことができません。これにより、非常に卑劣なバグが発生します。'' = null標準ではない場合でも、これは最も適切なオプションです。
Lucio M. Tato

2
「 '' <> NULLである他のDBでは、データがnullまたは ''であるかどうかを「見る」ことができません」=>通常、DBツールはNULLを空の文字列とは異なる方法で表示します。実際、Oracle SQL DeveloperでもNULLは「(null)」と表示されます。これはNULLと空白を区別するためだと思いますが、NULLと空の文字列の違いとは無関係です。
Didier L

-6

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

OracleのNULLリンクの処理:

http://digitalbush.com/2007/10/27/oracle-9i-null-behavior/

http://jeffkemponoracle.com/2006/02/empty-string-andor-null.html


1
無効なデータ時間値?どういう意味かわかりません。ここに質問としてこれを投稿しましたか?

1
問題以前のスタックオーバーフロー-Oracleフォーラムから有用な情報が得られず、回避策を作成しました-メモを追跡してここに投稿します。
Cade Roux、

詳細は質問としてこちらに投稿してください。
Cade Roux、

-6

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

5年または6年ほど前、Oracleではnull文字列の扱いがnullとは異なりました。nullのように、null文字列はすべてに等しく、すべてとは異なりましたが(nullには問題ないと思いますが、null文字列は完全に間違っています)、少なくともlength(null文字列)は0を返します長さがゼロの文字列。

現在Oracleでは、length(null)はnullを返しますが、これは問題ないと思いますが、length(null string)もnullを返します。これは完全に間違っています。

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


「null文字列」とNULL値を区別するために必要な引用。Oracle以外のデータベースでは、VARCHARフィールドに値(ゼロ以上の文字)または値なし(NULL)、フルストップを設定できます。

2011年からの「5年または6年前」は10gのタイムフレームに該当します(10.1は2003年にリリースされ、2005年には10.2)。10gではNULL、null の処理にグローバルな変更はまったく導入されておらず、null値の文字列との違いはありませんでした。そのような違いは意味がありません。この答えは完全なファンタジーだと思います。
ウィリアムロバートソン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.