web-dev-qa-db-ja.com

ソフト削除のベストプラクティス(PHP / MySQL)

問題

商品や注文を扱うWebアプリケーションでは、元従業員(ユーザー)と彼らが扱った注文との情報と関係を維持したいと思います。廃止された製品とこれらの製品を含む注文との間の情報と関係を維持したいと思います。

ただし、元従業員の削除、廃止された製品、廃止された製品グループなど、管理インターフェイスを整理できるように従業員に求めています。

ソフト削除の実装を考えています。それで、通常どのようにこれを行うのですか?

私の当面の考え

私の最初の考えは「flag_softdeleted TINYINT NOT NULL DEFAULT 0 "ソフト削除可能である必要があるオブジェクトのすべてのテーブルの列。または、代わりにタイムスタンプを使用しますか?

次に、関連する各GUIに[削除済みを表示]または[削除解除]ボタンを用意します。このボタンをクリックすると、ソフト削除されたレコードが結果に含まれます。削除された各レコードには、[復元]ボタンがあります。これは意味がありますか?

あなたの考え?

また、関連するリソースへのリンクをいただければ幸いです。

27
user479911

それが私のやり方です。デフォルトが0のis_deletedフィールドがあります。次に、クエリはWHERE is_deleted = 0をチェックするだけです。

私は可能な限りハード削除を避けようとします。それらは時々必要ですが、私はそれを管理者専用の機能にします。そうすれば、ハード削除することはできますが、ユーザーは削除できません...

編集:実際、これを使用して、アプリに複数の「レイヤー」のソフト削除を含めることができます。したがって、それぞれがコードである可能性があります。

  • 0->削除されません
  • 1-> Soft Deleted、管理ユーザーの削除済みアイテムのリストに表示されます
  • 2->ソフト削除済み、管理者ユーザー以外のユーザーには表示されません
  • 3->開発者にのみ表示されます。

他の2つのレベルがあると、マネージャーと管理者は、削除されたリストが長くなりすぎた場合でもクリーンアップできます。また、フロントエンドコードはis_deleted = 0をチェックするだけなので、フロントエンドに対して透過的です...

32
ircmaxell

ソフト削除の使用は実装するのが一般的なことであり、次のような多くのことに非常に役立ちます。

  • ユーザーが何かを削除したときにユーザーのデータを保存する
  • 何かを削除するときに自分のデータを保存する
  • 実際に何が起こったかの実績を保持する(一種の監査)
  • エトセトラ

私が指摘したいことが1つありますが、ほとんどの人が見逃していることです。それは常に後部であなたを噛むために戻ってきます。アプリケーションのユーザーは、deleteについてあなたと同じように理解していません。

削除にはさまざまながあります。一般的なユーザーは、次の場合にコンテンツを削除します

  • 間違いを犯し、悪いデータを削除したい
  • 画面に何かを見たくない

問題は、削除のintentionを記録しないと、アプリケーションが誤ったデータ(作成されるべきではなかった)とを区別できないことです。歴史的に正しいデータ。

次のデータをご覧ください。

PRICES | item | price | deleted |
       +------+-------+---------+
       |   A  |  101  |    1    |
       |   B  |  110  |    1    |
       |   C  |  120  |    0    |
       +------+-------+---------+

一部のユーザーは、アイテムBを販売しなくなったため、そのアイテムの価格を表示したくありません。それで彼はそれを削除します。別のユーザーがミスでアイテムAの価格を作成したため、意図したとおりにアイテムAを削除し、アイテムCの価格を作成しました。さて、すべての製品の価格のリストを見せていただけますか?いいえ、誤っている可能性のあるデータを表示する必要があるか(A)、現在の価格以外のすべてを除外する必要があるため(C)。

もちろん、上記はさまざまな方法で処理できます。私のポイントは、[〜#〜] you [〜#〜]は、[〜#〜] you [〜#〜]の意味を明確にする必要があるということです。削除し、ユーザーが誤解しないようにしてください。 1つの方法は、ユーザーに選択(非表示/削除)を強制することです。

9
Ronnis

そのテーブルにヒットする既存のコードがある場合は、列を追加してテーブルの名前を変更します。次に、アクティブなレコードのみを選択する現在のテーブルと同じ名前のビューを作成します。そうすれば、既存のコードが壊れることはなく、ソフト削除列を持つことができます。削除されたレコードを表示する場合は、ベーステーブルから選択します。それ以外の場合は、ビューを使用します。

5
HLGEM

あなたが言ったように、私はいつも削除済み列を使用しました。それ以上のものは実際にはありません。レコードを削除する代わりに、deletedフィールドをtrueに設定するだけです。

私が作成したコンポーネントの中には、ユーザーが削除されたすべてのレコードを表示して復元できるものもあれば、削除済み= 0のすべてのレコードを表示するものもあります。

1
simshaun

あなたのアイデアは理にかなっており、本番環境で頻繁に使用されますが、それを実装するには、新しいフィールドを説明するためにかなりのコードを更新する必要があります。別のオプションは、「ソフト削除された」レコードを別のテーブルまたはデータベースにアーカイブ(移動)することです。これも頻繁に行われ、問題は(再)プログラミングではなくメンテナンスの問題になります。 (テーブルトリガーを削除に反応させて、削除されたレコードをアーカイブすることができます。)

アーカイブは、本番コードの大幅な更新を避けるために行います。ただし、deleted-flagフィールドを使用する場合は、それをタイムスタンプとして使用して、ブール値以外の追加の有用な情報を提供します。 (Null =削除されません。)レコードの削除を担当するユーザーを追跡するために、DeletedByフィールドを追加することもできます。 2つのフィールドを使用すると、誰がいつ何を削除したかを示す多くの情報が得られます。 (2つの追加フィールドソリューションも、アーカイブテーブル/データベースで実行できるものです。)

1
Paul Sasik

私が遭遇した最も一般的なシナリオは、あなたが説明するものであり、tinyintまたはbitまたはIsActiveのステータスを表すIsDeletedですらあります。これが「ビジネス」データと「永続性」データのどちらと見なされるかに応じて、ストアドプロシージャに直接含まれ、アプリケーションコードに認識されないなど、可能な限り透過的にアプリケーション/ドメインロジックに組み込まれる場合があります。しかし、これはあなたのニーズにとって正当なビジネス情報であるように思われるので、コード全体で知る必要があります。 (したがって、ユーザーは、提案したように、削除されたレコードを表示できます。)

私が見たもう1つのアプローチは、2つのタイムスタンプの組み合わせを使用して、特定のレコードのアクティビティの「ウィンドウ」を表示することです。それを維持するのはもう少しコードですが、利点は、事前に決められた時間にそれ自体をソフト削除するようにスケジュールできることです。たとえば、期間限定の商品は、作成時にそのように設定できます。 (レコードを無期限にアクティブにするには、最大値(または不条理に遠い将来の日付)を使用するか、問題がなければ終了日をnullにすることができます。)

その後、もちろん、時々削除/削除解除されるものについてさらに検討し、そのためのある種の監査を追跡します。フラグアプローチは現在のステータスのみを認識し、タイムスタンプアプローチは最新のウィンドウのみを認識します。ただし、監査証跡のように複雑なものは、問題のレコードとは別に保存する必要があります。

0
David