web-dev-qa-db-ja.com

Oracleでのnullと空の文字列

可能性のある複製:
Oracle 9iが空の文字列をNULLとして扱うのはなぜですか?

Oracle 10gにはTEMP_TABLEという名前のテーブルがあり、2つの列のみがあります-デモのためにiddescriptionです。

idNUMBER(35, 0) not null型のシーケンス生成主キーであり、列DESCRIPTIONVARCHAR2(4000) not nullの型です。

この場合の基本的なテーブル構造は、次のようになります。

+--------------+-----------+---------------+
|Name          | Null?     | Type          |
+--------------+-----------+---------------+
|ID            | NOT NULL  | NUMBER(35)    |
|DESCRIPTION   | NOT NULL  | VARCHAR2(4000)|
+--------------+-----------+---------------+

このテーブルを作成した後、次のINSERTコマンドを代わりに挿入しようとしています。

INSERT INTO temp_table (id, description) VALUES (1, null); ->unsuccessful
INSERT INTO temp_table (id, description) VALUES (2, '');   ->unsuccessful

not null制約がDESCRIPTION列に適用されるため、どちらも明らかなように失敗します。

どちらの場合でも、Oracleは文句を言います

ORA-01400: cannot insert NULL into ("WAGAFASHIONDB"."TEMP_TABLE"."DESCRIPTION")

空の文字列は、OracleでNULL値として扱われます。


DESCRIPTION列にnot null制約をドロップすると、基本的なテーブル構造は次のようになります

+--------------+-----------+---------------+
|Name          | Null?     | Type          |
+--------------+-----------+---------------+
|ID            | NOT NULL  | NUMBER(35)    |
|DESCRIPTION   |           | VARCHAR2(4000)|
+--------------+-----------+---------------+

指定されたINSERTコマンドは両方とも成功します。 null値を持つ行と、''DESCRIPTION列に空の文字列TEMP_TABLEを持つ2つの行を作成します。

さて、次のSELECTコマンドを発行すると、

SELECT * FROM temp_table WHERE description IS NULL;

次に、一方がnull値を持ち、もう一方がDESCRIPTION列に空の文字列''を持つ両方の行をフェッチします。

ただし、次のSELECTステートメントは、TEMP_TABLEから行を取得しません

SELECT * FROM temp_table WHERE description='';

DESCRIPTION列に空の文字列がある行も取得しません。


おそらく、Oracleはnullの値と空の文字列''を異なる方法で処理しているように見えますが、INSERTステートメントとnull値と空の文字列''は、not null制約を持つ列に挿入されません。なぜそうですか?

72
Tiny

これは、Oracleが空の文字列を内部的にNULL値に変更するためです。 Oracleは単に空の文字列を挿入させません。

一方、SQL Serverでは、達成しようとしていることを実行できます。

ここには2つの回避策があります。

  1. 「説明」フィールドが有効かどうかを示す別の列を使用します
  2. 空の文字列を保存する「説明」フィールドにダミー値を使用します。 (つまり、実際のデータがそのような説明値に遭遇しないと仮定して、フィールドを「stackoverflowrocks」に設定します)

もちろん、両方とも愚かな回避策です:)

88
Vaibhav Desai

Oracleでは、空のvarchar2とnullは同じように扱われ、あなたの観察はそれを示しています。

あなたが書くとき:

select * from table where a = '';

書くのと同じ

select * from table where a = null;

a is nullではありません

これは決してtrueと等しくならないため、行を返さないでください。挿入についても同じです。NOTNULLは、nullまたは空の文字列(nullとして扱われる)を挿入できないことを意味します。

28
DazzaL