Life is Really Short, Have Your Life!!

ござ先輩の主に技術的なメモ

論理削除の前に別テーブルに切り出せるかどうかを考えよう

めっちゃよくまとまっているので、大変助かりました。

blog.mogmet.com

t-wada氏の「とりあえず削除フラグはアカン」については、僕も全く同感です。論理削除をしなければならないビジネス上の理由がスッポリ抜け落ちている。「とりあえず削除フラグ立てて何かあれば戻せるようにすればいいンゴ」ってのは論理設計を放棄していると言い換えても良いし、「ユーザーの言葉ではない」という指摘も重要。こちらに書かれています。

ledsun.hatenablog.com

じゃ、フラグやめてどーすんのって話。フラグを立てたくて立てる人はおらん(はず)。「削除フラグを追加するとSELECT時に常にWHERE句で削除フラグを引っ掛ける必要があるのでクソ」→「削除日や状態カラムを使おう」では解決にならん。t-wada氏の資料でも解決策で上げられてたけど「×」マークがついてます。下記に変わっても誰も嬉しくないと思う。

/* フラグ */
where is_deleted = 0
/* 削除日時 */
where delete_at =< now()
/* 状態 */
where status != '削除'
/*WHY JAPANESE PEOPLE!!! */

カラムに状態を持たせるのは危険です。特にその状態カラムをWHERE句で照合して何かしらのロジックを実行するようなプログラムを書いてしまう場合に、非常に危険。状態を示す固定文字列なら問題無いだろうが、状態が変わることでビジネス上の行動が変わるのであれば、もうそれはひとつのイベント発生ですよね。

その論理削除、実はイベントの発生じゃないですか?

論理削除の一例を上げてくれたので、それに乗っかる。

  • 社員が退職(・転属)する
  • 売掛金の回収を諦めて)売上を打ち消す
  • 「お知らせメッセージ」を公開日がくるまで非表示にする
  • 既読メッセージを表示しない
論理削除フラグという名の死亡フラグ - @ledsun blog

この退職や転属が、とてもわかりやすい例だと思う。

退職を示す削除フラグを設けたら、今までと同様にWHERE句で常に付いて回る問題は解決しない。削除日を持たせる(退職だと退職日)設計にしても、退職日がセットされているかどうかをWHERE句で引き回す必要があるので、めんどいまま。状態カラムに退職なんて持たせ(以下略

退職することを記録したいなら、退職テーブル作ればいいんじゃないでしょうか。これで社員テーブルからそのデータは消せます。おらん奴はいらんねん。転属は転属(履歴)テーブルを作ればいい。何度も発生する可能性がある。社員テーブルは社員の情報のみを格納すべきで、社員に従属するイベント(退職・転属)は、イベント管理用のテーブルを作れば大きく破綻しないと思います。

間違えちゃったから戻したい系

これね。これが困っちゃうよ。物理削除したものを戻す必要性があるのなら、削除データをアーカイブ用テーブルに移すことになるだろう。そこまでやるか、と。

結局ワイ将は、受注に対してフラグを立てちゃったんだ。同じ受注を二度と出荷しないように、出荷したら未出荷受注一覧から消す必要があった。受注履歴は集計・分析して売れ筋や昨対比等を判断したいから、受注データを出荷時に消すことは出来ない。でも、間違えて出荷しちゃったので未出荷に戻したいとみなさん仰る。ま、もう、YesかNoしかないから、フラグでもええかと... 受注にはビジネス上の理由で出荷・未出荷の判別が必要だから、WHERE句に付いて回るのが正しいのやと。そう思ったンゴ。

とりあえずこの本を読みなさい

DB論理設計はこの本を読めば生きていける。

楽々ERDレッスン (CodeZine BOOKS)

楽々ERDレッスン (CodeZine BOOKS)