データベースのNULLの判定にいきなりハマった
C#の記事
- C#でMySQLを使う - 1.開発環境インストール
- C#でMySQLを使う - 2.SELECT・画面表示
- C#でMySQLを使う - 3.追加更新と削除
- C#でのデータベースのデータのNULLかどうかの判定【この記事】
- C#のdelegate(デリゲート)と=>(ラムダ式)はC言語の関数へのポインタに似た扱い
- 動的にコントロールを追加 - 1.ボタンクリック
- 動的にコントロールを追加 - 2.テキストボックスの参照
- 動的にコントロールを追加 - 3.DB(MySQL)から動的に作成
C#の慣習で、取得失敗といえば「null」だろうという感覚でソースコードを組んでいた私。。。( ´ •̥ ̫ •̥ ` )実はデータベースに関してはハマったことがあります。
それはC#のデータベースのNULLの扱いは、データベース(SQL)の世界ではNULLは不定値であり、C言語やJavaでいう「完全なゼロ」を意味するnullとは別物である現実を知らずに、DBのNULLを「<変数> == null」で判定してしまったということです。
DBの世界ではNULLは無効な不定値を意味するので、今になって、さすがに混同なんてできないものだって反省しました…
環境
- OS:Windows 10 Pro
- 開発環境:Visual Studio 2019
- データベース:MySQL 5.7
もともとのソースコードの状態
今回は、MySQLをC#に導入したとき
のプログラムを組んでみたのですが、実際のデータは以下のようになっています。
id | name | memo |
---|---|---|
1 | テスト用 | Only for testing. |
2 | π | 3.14159265358797323... |
4 | 3.14 | NULL |
6 | 超難しい | Difficult Testing |
7 | 難しい | テスト |
8 | √5 | 2.2360679... |
実際には、memoの一部にはNULLが含まれているため、以下のコードでは、実行すると空白で表示されてしまったんです。
listBox1.Items.Add(row[1]);
listBox2.Items.Add(row[2]);
「== null」ではNULLの判定ができなかった
そこで、取得したmemoはrow[2]に該当するので「row[2] == null」「row[2] != null」で、NULLかどうかの判定をしたのですが…
listBox1.Items.Add(row[1]);
if (row[2] != null) {
listBox2.Items.Add(row[2]);
}
else {
listBox2.Items.Add("(未設定)");
}
うまく比較されていませんでした( ´ •̥ ̫ •̥ ` )
正しいDBのNULLの判定
データベースのNULLは不定値である
最近はDBのNULLについて理解を深めていったけど、データベースの世界では、NULLは不定値を意味するのであって、C言語やJavaのように、完全無効なゼロを意味するものではないということで、C言語でDBのNULLについていうと、初期化されていない変数みたいなもので、不安定な値を含んでいるものに近いらしい。
そうなれば、DBのNULLを「==」「!=」演算子で比較しようとしても、当然うまくいかないのかもね。。。
正しい比較のしかた
っということで、正しい比較としては、DBNull.Valueというものが用意されているので、その値に等しければ、取得したデータはNULLだということが判別できる
listBox1.Items.Add(row[1]);
if (!row[2].Equals(DBNull.Value)) {
listBox2.Items.Add(row[2]);
}
else {
listBox2.Items.Add("(未設定)");
}
これでNULLの場合の比較ができた(♥´꒳`*)
参考文献
1. [C#]DataRowの値がNullかチェックする方法
2. DBNull.Value フィールド - Microsoft .NET 公式