論理削除フラグを考える
長年納得の行かなかった物の一つに論理削除フラグというものがある。
DBのテーブルの端っこにいる、更新時刻とかと一緒にいて、データが削除されたことを示すフラグだ。
なんでこんなことをして、レコードそのものをdeleteしないかというと、削除したという記録を残すためっていうのが主な理由。
ただ、このフラグのせいで、アプリの作りが直感的にならなくなっている。
- アプリからデータの削除を行う処理がdeleteじゃなくてupdateになる
- selectのwhereに論理削除フラグが必ず入る
このへんがイケてない。
では、「データを記録を残しつつ削除しする」という処理を行うのは誰の仕事なのか?
自分はDBの仕事だと思う。
削除処理において、アプリからDBへの指示は、「このレコードを削除して」であって、「ここのフラグを更新して(削除してあるデータかはこっちで判断するから)」ではないからだ。
この削除してあるデータか判断するのはDBの仕事だろう。自分が担当すべき仕事はしっかりやろう。それはリアルでも一緒。
だから、削除されたという記録を残しながらの削除という機能はDBで実現すべきではないだろうか。本来DBがやるべき仕事をDBがやらずにアプリでやっている。そこに違和感があったわけだ。
じゃあ、これをDBで実現するにはどうすればいいかという話が出てくる。
自分としては同じ構造のテーブルを用意して(削除テーブルとする)、そこに削除されたレコードを入れておくのがいいと思う。このデータの移動はトリガーを使うのが構造的にまとまっている感じがする。
この削除テーブルとトリガーによる論理削除は論理削除フラグの問題を克服している
- アプリからはdelete文の実行で良い
- テーブル単位で見れば物理削除されているので、uniq indexも使える
- テーブルに無駄なレコードが残らない。論理削除フラグにindexみたいな筋悪から開放
え、データの復元?
削除テーブルからinsert Selectでやればいいでしょ。
あと、トリガーが良くないなんて言う人がいるけど、アプリの仕事をDBでやらせるトリガーが良くないのであって、本来DBがやるべき仕事を実現するためのトリガーは積極的に使うべきだと思う。