web-dev-qa-db-ja.com

SQLは等しくないクエリでnull値を表示しませんか?

これは単なる好奇心からの質問ですが、データベースを調べて、列の1つに対するクエリを使用してテーブルからデータを取得しています。この列には、null012。クエリを次のように実行すると:

SELECT * FROM STATUS WHERE STATE != '1' AND STATE != '2';

実行と同じ結果が得られます。

SELECT * FROM STATUS WHERE STATE = '0';

つまりクエリされた列のtopコマンドにnull値を持つ行は結果から省略されているようですが、これは常にSQLで発生しますか?

Oracle SQL Developerを介してコマンドを実行しています。

38
Alexei Blue

いくつかの言語では、NULLは異なる方法で処理されます。ほとんどの人は、truefalseがブール式の唯一の比較可能な値である2値ロジックについて知っています(falseは0と定義され、trueは何でもそうしないと)。

標準SQLでは、 値論理 について考える必要があります。 NULLは実際の値として扱われず、「不明」と呼ぶことができます。そのため、値が不明な場合、stateが0、1、またはその他のものであるかどうかは不明です。したがって、NULL != 1NULLになります。

これは、NULLの可能性があるものをフィルター処理する場合は、NULL値を自分で処理する必要があると結論付けています。構文も異なることに注意してください。NULL値は、x IS NULLではなくx = NULLとのみ比較できます。論理演算の結果を示す真理値表については、Wikipediaを参照してください。

32
Alex

はい、それは正常です、あなたはおそらくそれを修正するためにデータベース設定を置くことができます

ただし、コードを変更して、そのようなことを行うことができます。

SELECT * FROM STATUS WHERE STATE != '1' OR STATE != '2' or STATE is null;

詳細はこちらをご覧ください: http://www.w3schools.com/sql/sql_null_values.asp

9
GregM

複数のorwhereは、すぐに読みにくくなり、結果が不確かになる可能性があります。

余分な括弧とINステートメント(この場合は_NOT IN_)の使用をお勧めします。

SELECT * FROM STATUS WHERE (STATE NOT IN ('1', '2')) or STATE is null;

実装はデータベースベンダーによって異なる場合がありますが、上記の明示的な構文により結果を確認する必要があります。

5
Michael Durrant

NVLは次のように使用します:SELECT * FROM STATUS WHERE NVL(STATE,'X') != '1' AND NVL(STATE,'X')!= '2';

2
Madam Zu Zu

research Oracle behaviorのスクリプトを作成しました:



create table field_values
(
is_user_deletable VARCHAR2(1 CHAR),
resource_mark VARCHAR2(3 CHAR)
)

insert into field_values values (NULL, NULL);
insert into field_values values ('Y', NULL);
insert into field_values values ('N', NULL);

select * from field_values; -- 3 row

-- 1 row, bad
update field_values set resource_mark = 'D' where is_user_deletable = 'Y'; 
update field_values set resource_mark = 'D' where is_user_deletable <> 'N'; 
update field_values set resource_mark = 'D' where is_user_deletable != 'N'; 
update field_values set resource_mark = 'D' where is_user_deletable not in ('Y');

-- 2 rows, good, but needs more SQL and more comparisons. Does DB optimizes?
update field_values set resource_mark = 'D' where is_user_deletable = 'N' or is_user_deletable is null; 

-- it better to have ('Y' and NULL) or ('N' and NULL), but not 'Y' and 'N' and NULL (avoid quires with https://en.wikipedia.org/wiki/Three-valued_logic)
-- adding new column which is 'Y' or 'N' only into existing table may be very long locking operation on existing table (or running long DML script)

0
Dzmitry Lahoda