質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.49%

論理削除以外の解決方法

解決済

回答 2

投稿

  • 評価
  • クリップ 1
  • VIEW 2,602
退会済みユーザー

退会済みユーザー

 環境情報

MySQL 5.7系
アプリケーションはRuby on Railsを使用

 DDL

自社システムのDDL(架空のものです)を以下に記載します

-- マスタ系テーブル
--------------------------------------------------------------------------------

-- プラン情報
CREATE TABLE `plans` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
);

-- 宿泊施設の部屋
CREATE TABLE `rooms` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
);

-- 予約情報
CREATE TABLE `reservations` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
);

-- 中間テーブル
--------------------------------------------------------------------------------

-- プラン情報-宿泊施設の部屋 中間テーブル
CREATE TABLE `plan_rooms` (
  `plan_id` int(11) NOT NULL,
  `room_id` int(11) NOT NULL,
  UNIQUE KEY `uidx_plan_rooms` (`plan_id`,`room_id`),
  CONSTRAINT `fk_02` FOREIGN KEY (`plan_id`) REFERENCES `plans` (`id`) ON DELETE CASCADE,
  CONSTRAINT `fk_03` FOREIGN KEY (`room_id`) REFERENCES `rooms` (`id`) ON DELETE CASCADE
);

-- 予約-部屋中間テーブル
CREATE TABLE `reservation_rooms` (
  `reservation_id` int(11) NOT NULL,
  `room_id` int(11) NOT NULL,
  UNIQUE KEY `uidx_plan_rooms` (`reservation_id`,`room_id`),
  CONSTRAINT `fk_04` FOREIGN KEY (`reservation_id`) REFERENCES `reservations` (`id`) ON DELETE CASCADE,
  CONSTRAINT `fk_05` FOREIGN KEY (`room_id`) REFERENCES `rooms` (`id`) ON DELETE CASCADE
);

 前提条件

※架空の設定なので、〇〇ならばという仮定は不可能

登場人物

  • 自社 販売業者から部屋・予約情報の提供を受け、プランを販売業者へ提供する
  • 販売業者 プランを消費者へ販売して、宿泊施設の部屋・予約情報を自社へ提供する 数十社存在する

データソース

  • プラン系テーブル(plans, plan_rooms)のデータは自社のシステムで作成・変更が行われる
  • 部屋/予約系テーブル(rooms, reservations, reservation_rooms)のデータは販売業者からAPI経由で取り込まれる
  • 実際には取り込み先ごとにaaa_rooms, bbb_rooms, ccc_roomsと数十種類に分かれている

アプリケーション仕様

  • 部屋のデータは販売業者システム上からある時点で取り込めなくなる
  • 販売業者システム上から取り込めなくなった部屋は自社システム上では表示してはならない
  • 自社システム上ではプラン-部屋テーブルをもとに、プラン詳細画面で部屋情報を表示する必要がある(自社システム上では部屋テーブルは物理削除できない)

 質問

部屋が販売業者システム上で物理削除された場合に、roomsテーブル(またはここに書かれていない新規のテーブルでも可)でどのように表現するべきか。

roomsはplan_rooms, reservation_roomsからの外部キーを持つため物理削除はできません。
そのため単純に考えるなら、rooms.is_deletedを設けてWHERE文で除外するという案があると思います。

しかし参考文献に記載した例では「論理削除」を避けるべきという意見をよく見かけました。
このパターンの場合に「論理削除(販売業者から取り込めなくなったフラグ)」を使用しない対応方法を教えていただけませんでしょうか。

 参考文献

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • yambejp

    2017/05/22 20:11

    テーブル構造だけでなくサンプルデータも提示して具体的な挙動を特定して下さい

    キャンセル

  • 退会済みユーザー

    退会済みユーザー

    2017/05/23 12:11 編集

    実際は宿泊に関するシステムではなく、架空のテーブルを設けましたが余計にややこしくなってしまったようです。
    以下に質問内容を簡潔にまとめます

    - 他システムからデータをAPIで取り込んで、自社システムのDBに保存している
    - 保存されたデータは他のテーブルへの外部キーも持ち、JOINして使用されてる(= 自社システムではそのデータを業務仕様上削除できない)
    - 他システムではそのデータは物理削除され、APIに含まれなくなることがある
    - また削除されたデータは自社システムでは表示してはいけない、そのため削除されたか否かを判別できるようにしなければならない
    - 判別できるようにするために `is_deleted` のようなフラグを持つ以外の方法はあるのか

    キャンセル

回答 2

checkベストアンサー

+3

「論理削除(販売業者から取り込めなくなったフラグ)」を使用しない対応方法

自分の感覚では、「論理削除フラグ」と「販売業者から取り込めなくなったフラグ」は別物だと考えています。

上に挙がっている記事の中にありますが、

DELETE_FLAG 自体の是非よりもその手前の話として、論理削除 == DELETE_FLAG というパターンの一つ覚えで設計する多くの人は、単純にちゃんと考えられてない場合が多いので、少し掘り下げて聞いてみると良いと思っています。

ということで、自分が設計を行うなら「状態」として「有効な部屋」「一時的に無効な部屋(改装中、休業中など)」「もう復活しない部屋(取り壊されたなど)」というフィールドをもたせる形にすると思います。

「すべての変化を記録するようなジャーナル型」は、理論的にはきれいなのかもしれませんが、RDBMSの普通の使い方とは少し違ってきますので、

  • 検索性能が出ない
  • RailsのActtiveRecordに合わないので、自分でモデル部に大幅な手を入れる必要がある

など、相当な手間を要することが予想されます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/23 12:03

    maisumakun様、ご回答ありがとうございます。

    以下にご回答いただいた内容に関する私の理解を記載いたします。

    > 自分の感覚では、「論理削除フラグ」と「販売業者から取り込めなくなったフラグ」は別物だと考えています。
    > ということで、自分が設計を行うなら「状態」として「有効な部屋」「一時的に無効な部屋(改装中、休業中など)」「もう復活しない部屋(取り壊されたなど)」というフィールドをもたせる形にすると思います。

    "販売業者から取り込めなくなった = 販売業者側システムで物理削除された"としてもそれはあくまで別システムの仕様であり、こちらのシステムではそれを論理削除ではなく状態として表現できる。

    また「テーブルに状態を持たせない」ほうが良いという意見も参考文献の中には見当たるが

    > 「すべての変化を記録するようなジャーナル型」は、理論的にはきれいなのかもしれませんが、RDBMSの普通の使い方とは少し違ってきますので、
    > 検索性能が出ない
    > RailsのActtiveRecordに合わないので、自分でモデル部に大幅な手を入れる必要がある

    検索性能とアプリケーションの仕様的にコストが高いので、このケースでは許容してもよいのでは。

    というようなご指摘と受け取ったのですが、正しく理解できていますでしょうか。

    キャンセル

+1

参照制約をON DELETE SET NULLで定義するのはどうでしょう

13.1.17.2 外部キー制約の使用

ただし、NOT NULL制約は同時に指定できなくなります
またこれにより、ユニーク制約もNULLを含むものは重複が許容されるようになります

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/23 11:17

    SVC34様、ご回答ありがとうございます。

    roomsへの参照制約をON DELETE SET NULLにすることで、roomsを物理削除できるようにするというご提案だと理解しました。

    > 自社システム上ではプラン-部屋テーブルをもとに、プラン詳細画面で部屋情報を表示する必要がある(自社システム上では部屋テーブルは物理削除できない)

    roomsの情報がなくなってしまうと上記要件を満たせなくなるため、この案は難しそうです。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.49%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る