SQL での Null の解析

怪我咯
怪我咯オリジナル
2017-04-05 11:52:371359ブラウズ

コンピューターやプログラミングの世界におけるNULLは、未知、不確実という意味です。漢訳では「空」ですが、この空(ヌル)はそれほど空(空)ではありません。 Null は未知の状態、つまり将来の状態を表します。たとえば、Xiao Ming がポケットにいくら持っているかはわかりませんが、それが 0 であるかどうかはわかりません。現時点では、Null はコンピュータで表すために使用されます。未知で不確実。

SQL に精通している人は Null について何の疑問も持たないでしょうが、それを包括的にまとめた記事を見つけるのはまだ困難です。英語版を見たので、かなり良いと思いました。

Tony Hoare は 1965 年に null を発明しました引用、そしてそれが彼が犯した「10 億ドルの間違い」であると考えましたが、50 年後の今日でも、SQL の null 値は依然として多くの一般的なエラーを引き起こします。最も衝撃的な状況を見てください。

Null はサイズ/等価性の判断をサポートしていません

次の 2 つのクエリでは、users テーブルにレコードがいくつあっても、返されるレコードは 0 行になります:

select * from users where deleted_at = null;
 
– result: 0 rows
 
select * from users where deleted_at != null;
 
– result: 0 rows

これはすべて、null が意味するためです。 「不明」タイプ。つまり、通常の条件演算子を使用して null を他の値と比較することは意味がありません。 Null は Null と等しくありません (おおよその理解: 未知の値が未知の値と等しくなることはあり得ず、この 2 つの値の間の関係も不明です。そうでないと数学と論理が台無しになります)。

: 次の SQL は

MySQL

に適しています。Oracle の場合は、... from Dual;

select null > 0;
 
– result: null
 
select null < 0;
 
– result: null
 
select null = 0;
 
– result: null
 
select null = null;
 
– result: null
 
select null != null;
 
– result: null
を追加する必要があります。値を null と比較する正しい方法は、is キーワードを使用することです、そして is not 演算子:
select * from users
 
where deleted_at is null;
 
– result: 所有被标记为删除的 users
2 つの列の値が異なるかどうかを判断したい場合は、 isdistinct from:

select * from users
 
where has_address is distinct from has_photo
 
– result: 地址(address)或照片(photo)两者只有其一的用户

not in と Null

サブクエリ (subselect) は非常に便利です。便利なデータフィルターメソッド。たとえば、パッケージを持たないユーザーにクエリを実行したい場合は、次のようなクエリを作成できます:

select * from users 
 
where id not in (select user_id from packages)

ただし、このとき、packages テーブルの行の user_id が null の場合、問題が発生します。返された結果は空です! なぜこの奇妙なことが起こるのかを理解するには、SQL コンパイラーが何をするのかを理解する必要があります。より簡単な例を次に示します:

select * from users 
 
where id not in (1, 2, null)
この SQL ステートメントは次のように変換されます:

select * from users 
 
where id != 1 and id != 2 and id != null

id != であることがわかります。 null 結果は不明な値、null です。任意の値と null の間の AND 演算の結果は null なので、他の条件と同等ではありません。この結果の理由は、null の論理値が true ではないためです。

条件が逆の場合はクエリ結果に問題はありません。 次に、パッケージを使用してユーザーにクエリを実行します。

select * from users 
 
where id in (select user_id from packages)

同様に、簡単な例を使用できます:

select * from users
 
where id in (1, 2, null)

この SQL は次のように変換されます:

select * from users 
 
where id = 1 or id = 2 or id = null

where 句は一連の or 条件であるため、そのうちの 1 つの結果は null になります。も無関係です。 true 以外の値は節の他の部分の計算結果に影響を与えず、無視されるのと同等です。

Null とソート

ソートの際、Null 値が最大であるとみなされ、降順 (降順) でソートする場合、Null 値が最初にランク付けされるため、これでは頭が痛くなります。 次のクエリはスコアに基づいてユーザーのランキングを表示することですが、スコアのないユーザーを上位にランク付けします!

select name, points
 
from users
 
order by 2 desc;
 
– points 为 null 的记录排在所有记录之前!

この種の問題を解決するには 2 つのアイデアがあります。最も簡単な方法は、Coalesce を使用して null の影響を排除することです:

– 在输出时将 null 转换为 0 :
 
select name, coalesce(points, 0)
 
from users
 
order by 2 desc;
 
– 输出时保留 null, 但排序时转换为 0 :
 
select name, points
 
from users
 
order by coalesce(points, 0) desc;

ソート時に null 値を先頭に置くか最後に置くかを指定する、データベース サポートを必要とする別の方法があります:

select name, coalesce(points, 0)
 
from users
 
order by 2 desc nulls last;

もちろん、nullゼロで除算する算術演算を処理する場合など、エラーの発生を防ぐためにも使用できます。

0による除算

0による除算は、非常に痛ましいエラーです。昨日は正常に動作していた SQL が、0 で割ると突然異常が発生しました。一般的な解決策は、最初に case ステートメントを使用して分母が 0 かどうかを判断し、次に除算演算を実行することです。

select case when num_users = 0 then 0 
 
else total_sales/num_users end;
ase文の使い方が実に醜く、分母が使い回されています。単純な状況であれば問題ありませんが、分母が非常に複雑な

の場合は、悲劇が起こります。読みにくく、保守や変更も難しく、注意しないと、たくさんのバグがあります

この時点で、null の利点を見てみましょう。nullif を使用して、分母が 0 の場合に null になります。このようにして、num_users = 0 の場合、返される結果は報告されません。 nullになります。

select total_sales/nullif(num_users, 0);
 
nullif 是将其他值转为 null, 而Oracle的 nvl 是将 null 转换为其他值。
nullは望まないが、0や他の数値に変換したい場合は、前のSQLに基づいてcoalesce関数を使用できます:

select coalesce(total_sales/nullif(num_users, 0), 0);
 
null 再转换回0

結論

トニー・ホアは自分の間違いを後悔するかもしれないが、少なくともヌルの問題は簡単に解決できるので、新しい究極の技を練習し、ヌル(無効化)によって掘られた効果のない穴から離れてください!


以上がSQL での Null の解析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。