DoorKeeper
http://sqlap.doorkeeper.jp/events/8213
以下の書籍をターゲットとした読書会なのです。
![]() | SQLアンチパターン (2013/01/26) Bill Karwin 商品詳細を見る |
場所はいつもの湯島、株式会社アルティネットさんです。
いつも会場提供ありがとうございます。
参加者は12人かな。
新規参加が一人ありましたが顔見知りなので、実質全員、顔見知り。
前回の読書会は11/20だったので、この日は2か月ぶりの読書会でした。
12月は読書会メンバーで忘年会をやったんですが、お料理もお酒も、とっても美味しかったです。
んで今回は2014年初の読書会ということで、参加者全員が最初に一言、今年の抱負を宣言しました。
ちなみに私の抱負はというと・・・、お正月明けに体重計に乗ったら、103kgと初の3桁大台に乗ったので(ぉ
今年の抱負は「体重を
・・・体重を測るとTweetされる体重計を今年購入しました。測るたびにこんなカンジで投稿されます。
My weight: 99.8 kg. [ 体重計とTwitterの連携による自動投稿 ] http://t.co/OuPwXMaY8X
— makopi23 (@makopi23) 2014, 1月 23
皆さんからの抱負は、技術系のチャレンジネタや、健康に関する抱負が多かったですね~
いろんな目標を聞くと、俺も頑張らなきゃ、って身が引き締まる思いです。
さて、今回から第Ⅲ部ということで、13章「フィア・オブ・ジ・アンノウン(恐怖のunknown)」がターゲットでした。
■13章の説明
今回は @akuraru さんがスライドを作成して紹介してくださいました。
3値論理やNULLIF関数を使った考察なども追加されていて良いですね~
■ディスカッション
今回もディスカッションしたいネタをみんなで付箋に書き出しました。

前日にミックさんのNULLに関する記事を読んでたんですが、ミックさん絡みの付箋もいくつか見られました。
NULL撲滅委員会 http://t.co/S7eDDkoDJY #sqlap
— makopi23 (@makopi23) 2014, 1月 23
この記事と今回の13章を合わせて読むことで、大変参考になります。
以下、個人メモ。
---
■スライドP.13のNULLIF関数
・MySQLだとNULLIF関数とIFNULL関数がある。
・NULLIF(式1,式2)は引数を2つとって、引数が等しい場合にNULLを返し、異なる場合に第一引数を返す関数。
・IFNULL(式1,式2)は引数を2つとって、第1引数がNULLなら第2引数の式を実行する関数。
・Oracleだと、NULLIF関数と同等の関数としてNVL関数がある。
■スライドP.19のPreparedStatement
・Where句の?にnullを当てはめて等号比較をしても、値がnullのレコードは1件もヒットしない。
・等号比較の代わりにIS NULL述語(書籍15.5.3節)を使う。
■NULLは値か?
・NULLは値というよりも、論理値みたいなもの。
・「何も無い」ことを示すタグみたいなもの。
■日付型カラムとNULL
・「退職年月日」のようなカラムがある場合の、在職中の社員への扱いは以下2種類がある。
①NULLを割り当てる
②2199/12/31のような遠い未来日を固定値で割り当てる
・①の利点:
- 未定なものにはNULL、という自然な発想に一致しやすいので違和感が無い。
・①の欠点:
- そのカラムを処理する際に、毎回NULL判定の分岐が必要となりクエリやコードが煩雑になる。
- IS NULL判定はインデックスが効かないので、性能に影響する。
・②の利点:
- NULL判定のコードが不要になり、クエリやコードがスッキリする。
- 処理性能面でも有利。
・②の欠点:
- 2199/12/31が意味を持つ未来までデータが移行され続けた場合に、業務的に破綻する。
- 固定値として9999/12/31を割り当てた場合、1970/1/1からの経過ミリ秒を表すUNIX Timeにおいて、32ビットで9999/12/31を表現することができず、オーバーフローで破綻する。(64ビットならOK)
・この例のように、「分かってないもの」に如何に名前や値を持たせるか、が設計の腕の見せ所。
■日付型カラムと状態
・日付型カラムで期間(Range)を表現した場合、ステートフルになる。
・例えば開店年月日と閉店年月日のカラムを持つテーブルの場合、その期間中にある店は開店していて、その期間外にある店は閉店している、という状態を持つことになる。
■4値論理
・3値論理(True, False, Null)におけるNULLを、以下のようにさらに2種類に分けた、4値論理というものがある。
①未知 (UNKNOWN)
②適用不能(Not Applicable)
・ミックさんのサイト「3値論理 ―― 神のいない論理」が参考になる。
■データベース界の2大宗教論争
・①主キー(ID)として、自然キー(ナチュラルキー)か代理キー(サロゲートキー)のどちらを用いるべきかの論争
・②カラムにNULLを許すか許さないかの論争(今回の13章が該当)
・この2つの考え方と、4値論理のNULLを2種類に分けるべきか否かという2つの考え方の組み合わせで、2×2=4象限になる。
・この4象限のどれを支持するかでカオスなバトルが繰り広げられるw
■NULLに関わる設計
・設計レベルではNULLを撲滅することはできるが、クエリレベルではNULLははチラホラ出てくる。
・論理設計でNULLが出てくるのはおかしい。論理設計の段階では「不明」という扱いで良いはず。
・物理設計の段階で、NULLにするか、パフォーマンスを考慮してNULLではなく未来日を入れて回避するか、などの設計を実施する。
・NOT NULL制約を付けると性能が遅くなる、という都市伝説があるが、きちんと測ってから議論すべき。
・NULLを許すカラム以外でもっと先に絞り込んでおけば、パフォーマンスにそれほど影響が無いように工夫できる。
・COUNT関数の引数にカラムを指定した場合、そのカラムにNULLが入っていた場合、そのレコードはカウントされない。
→ 実際のレコード数と異なるため、想定外の結果となる。ちなみにCOUNT(*)ならNULLがあってもOK。
・整数型のカラムに、NULLを避けるために-1を割り当てたりすると、SUMなどの集合演算で破綻する。
■ドイツ語の0
・ドイツ語での数字の読み方は、0:null(ヌル)、1:eins(アインス)、2:zwei(ツヴァイ)、…
・英語はZeroだが、ドイツ語はNullだった!
■NULLに関する意外な事故事例
・アメリカでNULLという苗字の人がいて、その人のデータをSOAP連携したときにシステムがコケたらしい。
・Nullという苗字の文字列をParseした際に、文字列からNullに変換され、システム連携でハマった・・・
・それまでシステムは正常だったのに、その人が入社するだけでシステムが破綻するとは恐るべきテロ・・・
・ググったら、ホントにあった事例みたいw 「Nullさんの憂鬱……自分の名前を検索すると社員検索アプリが死ぬ」
■JavascriptにおけるNullの扱い
・Javascriptではnullとundefinedがある。(参考:Qiita「null と undefined の違い」)
①null: 何かを返すべきであるが、返すものがない場合に使用する。意図的に使われる。
②undefined: ただ何もない状態。定義されていない変数、オブジェクトの定義されていないプロパティ、何もreturnしない関数の返り値などは全てundefined。
・Javascriptのバグで、"typeof null"とすると"object"が返ってくる。
■Not Null制約とDefault Null指定の共存
・MySQLでは、Not Null制約を付けたカラムにDefault Null指定ができるらしい。
・MySQLではNOT NULLなどの制約をかけているフィールドに対してNULLをinsertすると、それがint型のフィールドであれば0、char型のフィールドであれば''(空文字)にされてinsertされるらしい。
参考ブログ: ロウブロウな日記「MySQLのNOT NULL制約のフィールドにはNULL突っ込んでもエラーにならない」
・この挙動はMySQL5.0以降ではSTRICTモードにすることで回避できるらしい。
■Nullを含むカラムをOrder by句に指定した場合のソート順序
・order by句で列を指定してソートすると、デフォルトではNULLのデータは最後にソートされる。
・OracleではNULLS FIRTSTとNULLS LASTの指定ができる。
・NULLのデータを最初に持ってきてソートしたい場合はorder by句で列指定後、NULLS FIRSTを指定するとNULLのデータが最初にselectされ、その後NOT NULLのデータがソートされる。
・逆に、まずNOT NULLのデータをソートし、最後にNULLのデータを持ってきたい場合はNULLS LASTを指定する。
・参考サイト:NULLS FIRTSTとNULLS LAST
■アンチパターン:Nullの使用を避ける(13.2.4節)
・アンチパターンの設計例:
- 外部キー制約で「社員テーブル」へ参照を持たせていたカラムがある。
- そのカラムにNullを許したくないからといって、社員テーブル側に「存在しない社員」を表す社員を用意した。
- では、「存在しない社員」が所属する部署はどう表現するか・・・?
- じゃあ、「所属テーブル」に「存在しない社員へ割り当てるための、ダミーの部署」を用意しよう!
・上記のような設計をすると、ダミーの社員や部署などをどんどん作る必要が出てきて、弊害となる。
・さらに、ほとんどのクエリーで、ダミーの社員や部署を除外するための指定を追加する必要があり、煩雑になる。
■13章のタイトル「フィア・オブ・ジ・アンノウン」の命名について
・@t_wada さん曰く、「本書で一番アレなタイトル」とのことw
・「ジョジョの奇妙な冒険」におけるスタンドっぽい名称になった。
・ラスボスっぽい命名。
・この章が一番強そう。
・・・ワロタw
■読書会後のご飯
読書会後は、恒例のお食事会。今日は7人でお寿司を食べに行きました~

楽しむ時は、た、体重なんて気にしないっ・・・!(震え声
★感想:
「NULL」という1テーマに対し、非常に多岐にわたる議論が繰り広げられ、大変勉強になりました。
これまで「NULLを割り当てるのが当たり前」だと思っていた私にとって、かなりの衝撃でした。
いろんな考えや設計があるんだなぁ。。。
あと、年末にSQLアンチパターンが増刷になったそうです。おめでとうございます!
【速報】『SQLアンチパターン』増刷決定! ありがとうございます!! http://t.co/yOa9XtswRF #sqlap
— Takuto Wada (@t_wada) 2013, 12月 24
この読書会で見つかった誤植なども反映されているそうです。
参加者の皆様、ありがとうございました~
■おまけ:過去の「SQLアンチパターン読書会」ブログ
1章:SQLアンチパターン読書会 「ジェイウォーク」に参加しました
http://makopi23.blog.fc2.com/blog-entry-65.html
2章:SQLアンチパターン読書会 「ナイーブツリー」に参加しました
http://makopi23.blog.fc2.com/blog-entry-70.html
3章:SQLアンチパターン読書会 「IDリクワイアド」に参加しました
http://makopi23.blog.fc2.com/blog-entry-73.html
3章:SQLアンチパターン読書会 「続・IDリクワイアド」 に参加しました
http://makopi23.blog.fc2.com/blog-entry-77.html
4章;SQLアンチパターン読書会 「キーレスエントリー」 に参加しました
http://makopi23.blog.fc2.com/blog-entry-84.html
5章:SQLアンチパターン読書会 「EAV(エンティティ・アトリビュート・バリュー)」に参加しました
http://makopi23.blog.fc2.com/blog-entry-90.html
6章:SQLアンチパターン読書会 「ポリモーフィック関連」 に参加しました
http://makopi23.blog.fc2.com/blog-entry-94.html
7章:SQLアンチパターン読書会 「マルチカラムアトリビュート」に参加しました
http://makopi23.blog.fc2.com/blog-entry-97.html
8章:SQLアンチパターン読書会 「メタデータトリブル」 に参加しました
http://makopi23.blog.fc2.com/blog-entry-105.html
9章:SQLアンチパターン読書会 「ラウンディングエラー」 に参加しました
http://makopi23.blog.fc2.com/blog-entry-109.html
10章:SQLアンチパターン読書会 「サーティーワンフレーバー」に参加しました
http://makopi23.blog.fc2.com/blog-entry-115.html
11章:SQLアンチパターン読書会 「ファントムファイル」に参加しました
http://makopi23.blog.fc2.com/blog-entry-118.html
12章:SQLアンチパターン読書会 「インデックスショットガン」に参加しました
http://makopi23.blog.fc2.com/blog-entry-121.html