web-dev-qa-db-ja.com

NULLを使用する場合と空の文字列を使用する場合

私は主にMySQLとPostgreSQLに興味がありますが、一般的には次のように答えることができます。

  • 空の文字列をNULLと区別するのに役立つ論理的なシナリオはありますか?
  • 空の文字列を保存するための物理的なストレージの意味は...

    • ヌル?
    • 空の文字列?
    • 別の分野?
    • その他の方法で?
87
Maniero

レコードが、名前と住所の情報を収集するフォームからのものであるとしましょう。ユーザーがアパートに住んでいない場合、住所の2行目は通常空白になります。この場合の空の文字列は完全に有効です。私は、値が不明または指定されていないことを意味するためにNULLを使用する傾向があります。

物理ストレージの違いが実際に心配する価値があるとは思いません。データベース管理者として、私たちはより大きな魚を揚げる必要があります!

67
Larry Coleman

MySQLとPostgreSQLについては知りませんが、少し一般的に扱います。

DBMSには、NULLと ''の間でユーザーを選択できないOracleがあります。これは、両方を区別する必要がないことを明確に示しています。いくつかの迷惑な結果があります:

次のようにvarchar2を空の文字列に設定します。

Update mytable set varchar_col = '';

以下は同じ結果につながります

Update mytable set varchar_col = NULL;

ただし、値が空またはNULLの列を選択するには、次を使用する必要があります

select * from mytable where varchar_col is NULL;

使用する

select * from mytable where varchar_col = '';

構文的には正しいですが、行を返すことはありません。

一方、Oracleで文字列を連結する場合。 NULL varcharは空の文字列として扱われます。

select NULL || 'abc' from DUAL;

abcが生成されます。これらの場合、他のDBMSはNULLを返します。

値が割り当てられていることを明示的に表現したい場合は、「」のようなものを使用する必要があります。

そして、あなたは空ではないトリミングがNULLになるかどうか心配する必要があります

select case when ltrim(' ') is null then 'null' else 'not null' end from dual

します。

次に、 ''がNULLと同一ではないDBMSを調べます(SQL-Serverなど)。

''を使用する方が一般に簡単で、ほとんどの場合、両方を区別する必要はありません。私が知っている例外の1つは、列がいくつかの設定を表し、それらの空のデフォルトがない場合です。 ''とNULLを区別できる場合は、設定が空であることを表し、デフォルトが適用されることを回避できます。

26
bernd_k

作業しているドメインによって異なります。 NULLは値がないことを意味します(つまり値がない)が、空の文字列は長さがゼロの文字列値

たとえば、個人のデータを格納するテーブルがあり、Gender列が含まれているとします。値は「男性」または「女性」として保存できます。ユーザーが性別データを提供しないことを選択できる場合は、それをNULL(つまり、ユーザーが値を提供しなかった)およびnot空の文字列(ないため、値を持つ性別 '')。

17
Gan

覚えておかなければならないことの1つは、必須ではないフィールドがある場合に、存在する値は一意でなければならないため、空の値をNULLとして格納する必要があることです。それ以外の場合は、そのフィールドに空の値を持つタプルを1つだけ持つことができます。

また、リレーショナル代数とNULL値にはいくつかの違いがあります。たとえば、NULL!= NULLです。

10

また、日付のNULLの批評と3VLの問題を SQLおよびリレーショナル理論 (および日付の批評のルビンソンの批評 Nulls、3値論理、およびSQLのあいまいさ)に組み込むこともできます。批評日の批評 )。

両方とも関連するSOスレッド、 DBモデルからNULL可能な列を削除するためのオプション で詳細に参照および説明されています)。

6
Abie

新しい考え、NULL/NOT NULLの選択に大きな影響を与えるのは、フレームワークを使用している場合です。私はsymfony alotを使用し、許可NULLフィールドを使用することで、データを操作するときのコードとデータチェックの一部を簡素化します。

フレームワークを使用していない場合、または単純なSQLステートメントと処理を使用している場合は、追跡するのが簡単であると思われる方を選択します。空のフィールドをINSERTに設定するのを忘れることでNULLステートメントを実行しても面倒にならないように、私は一般的にNULLを好みます。

4
Patrick

Oracleで作業しなければならなかった( これは区別できない )私は次の結論に達しました。

  • 論理的な視点からそれは重要ではありません。 NULLと長さゼロの文字列を区別することで、DBMSに値が追加される説得力のある例は、実際には考えられません。

  • 以下から:ゼロレンズを許可しないNULLable列_''_(Oracle風のソリューション)またはゼロレンズを許可する_NOT NULL_列のいずれかがあります。

  • そして、私の経験から、_''_は、データの処理時にalotをより意味のあるものにします。通常、文字列の欠如を処理したいからです空の文字列として:連結、比較など.

注:私のOracleエクスペリエンスに戻るには、検索リクエストのクエリを生成するとします。 _''_を使用する場合、_WHERE columnX = <searchvalue>_を生成するだけで、等価検索で機能します。 NULLを使用する場合は、WHERE columnX=<searchvalue> or (columnX is NULL and serchvalue is NULL)を実行する必要があります。ば! :-)

2
Martin

また、デザインの観点からも異なります。

例えば.

CREATE TABLE t (
    id INTEGER  NOT NULL,
    name CHARACTER(40),
    CONSTRAINT t_PK PRIMARY KEY (id)
);

CREATE UNIQUE INDEX t_AK1 ON t (name);

次のようになります。

 \d t
          Table "public.t"
 Column |     Type      | Modifiers
--------+---------------+-----------
 id     | integer       | not null
 name   | character(40) |
Indexes:
    "t_pk" PRIMARY KEY, btree (id)
    "t_ak1" UNIQUE, btree (name)

いくつかのデータを挿入しましょう:

op=# insert into t(id, name ) values ( 1, 'Hello');
INSERT 0 1

op=# insert into t( id, name) values ( 2, '');
INSERT 0 1

op=# insert into t( id, name) values ( 3, '');

ERROR:  duplicate key value violates unique constraint "t_ak1"

次に、nullで試してみましょう。

op=# insert into t( id, name) values (4, null );

INSERT 0 1

op=# insert into t( id, name) values (5, null);

INSERT 0 1

これは許可されています。

Soooooo:nullは簡単な文字列でもその逆でもありません。

乾杯

2
Guy Birkbeck

理論について話す場合、Coddのルールでは、RDBMSはNULL値を特別な方法で処理する必要があるとしています。

正確にどのように使用されるかは、実際のドメイン-タスク-プロジェクト-アプリケーション-エリアに応じて、データベースアーキテクト次第です。

1
noonex