レコードステータス(保留、完了、ドラフト、キャンセルなど)を保存する方法


17

多くのアプリケーションでは、テーブルのレコードに「完了」、「ドラフト」、「キャンセル」などのステータスを設定する必要があります。これらのステータスを保存する最良の方法は何ですか?私がここで得ているものを説明するのは、*非常に短い)例です。

簡単なブログアプリケーションがあり、各投稿のステータスは、公開済み、下書き、保留中のいずれかです。

私がそれを見る方法は、データベースでこれをモデル化する2つの方法があります。

  1. Postテーブルには、ステータステキストを含むテキストフィールドがあります。
  2. Postテーブルには、PostStatusテーブル内のレコードのIDを含むステータスフィールドがあります

ここのブログの例は、非常に単純な例です。列挙型(サポートされている場合)で十分な場合があります。ただし、ステータスのリストはいつでも変更される可能性があることを考慮に入れて、質問への回答が欲しいので、追加または削除できます。

誰もがそれぞれの長所/短所を説明できますか?

乾杯!

これに関する私の最初の選択は、別のテーブルを使用し、正規化に適しているとステータスを調べる方が良いことです。正規化はデータベースに適しているといつも教えられてきました



「いつでも」とはどういう意味ですか?それは、ユーザーアクティビティの一部として、またはソフトウェアリリースサイクルの一部として意味しますか?
ケビンクライン

どちらも、ここで最もよく使用されているアプローチのいずれかです。したがって、ユーザーが新しいステータスを追加できる場合、またはプロジェクトの後半で新しいステータスが追加される場合
-veganista

データベースにテキストを保存することは、適切な非正規化かもしれません。組織がプロセスをどのくらいの頻度で変更するか(ステータス変更の可能性につながる)など、正確な詳細に依存する可能性があると思います。
ジェイディー

ユーザーが新しいステータスを追加できる場合、それはまったく別のことです。おそらく、作成中のユーザーなどのステータスを記録する必要があり、間違いなく別のテーブルが必要になります。
ケビンクライン

回答:


14

ステータスをインデックスとして別のテーブルに保存することは、不必要な複雑さです。ステータスを読みやすい方法でテーブルに直接保存します。アプリケーションコードでは、定数または列挙型を使用します。これにより、アプリケーションコードがシンプルになり、データレイヤーのデバッグが容易になります。

これはデータの非正規化ではなく、単に表現を変更するだけです。データベースが列挙を直接サポートしている場合は、それを使用します。それ以外の場合は、制約を使用して列の値を制限します。どちらかの方法で制約を設定します。列値に対する直接制約、または外部キー制約のいずれかです。

はい、ステータスをユーザーごとに異なる方法で提示する必要がある場合があります。これはプレゼンテーションの問題であり、永続層ではなくプレゼンテーション層で解決されます。


1
+ 1、dbのステータスのリストを保持する特定の必要性を除いて、これは一般的にそれを行うための最も簡単で、最も複雑な方法です。
GrandmasterB

2
あなたが変異日付をステータスアーキテクチャを変更したり、保管開始しない限り、これは、okです
LastTribunal

10

ステータステキストを保存することはIMOではなく、誰かが「完了」を「終了」と呼ぶべきだと判断し、データベースを更新し、誰かがテキストをハードコーディングした場合はプログラムを調べる必要があるためです。

多くのプログラムで見たものは、数値コード(1 =新規、2 =ドラフト、3 =検証中、4 =完了、99 =キャンセル)または短い英数字コード( "NEW"、 "DRA"、 "INV 「、「COM」、「CAN」)。後者は、コード(プログラム内またはデータベース内)を人間が読めるようにします。これは一般に良いことです。一方、数値コードを使用すると、「より大きい」または「より小さい」比較を簡単に実行できます。たとえば、

select * from myrecords where status < Status.Complete;

一部のばかもIDをハードコアできます。
モロン

IDのもう1つの利点は、ローカライズを提供する必要があることです。IDを使用して、リソース文字列を検索して表示できます。ハードコードされた文字列では、これは不可能です
アーミテージ

3
あなたが示したような「より大きい」または「より小さい」比較を使用してステータスを表示することは良い考えだとは思いません。この例のような単純なアプリケーションでは機能する可能性がありますが、より複雑なアプリケーションには適していません(ただし、そのことに気付いている
はず

1
@armitage:文字列を使用してルックアップを行うことは完全に可能です。:リソース名は文字列であるstatus.draft=Draught
ケビン・クライン

veganista:確かに、比較よりも大きい/小さいという困難はありますが、それを実行する大規模で複雑なシステムを見てきました。
-user281377

3

リレーショナルデータベースの3つのルール:

  1. ノーマライズ
  2. ノーマライズ
  3. ノーマライズ

したがって、あなたの質問はそれ自身に答えます。ステータスを独自のテーブル内に保持し、GUIDとしてGUID / UUIDを使用します。インデックス付きGUIDは非常に高速で、数値の増加に固有の問題を修正します。IDを使用すると、IDを使用して完了したすべての投稿をDBに要求するなどのクールなことができます。また、リレーショナルDBパラダイム内で作業しているため、非常に高速です。フィールドが1つしかない場合、DBはすべての行をループしてテキスト比較を実行する必要があります(おそらく変更されます)。これは非常に遅いです。

投稿ステータス名は変更できます。投稿ステータスに関する詳細情報は表に記載できます正規化するすべてが機能します

たとえば、ステータスレベルを追加情報として追加すると、ammoQの言及を比較できます。ただし、位置決めのキーに依存しないため、DBの整合性を損なうことなくステータスレベルを再配置できます。追加のレベルを挿入することもできます。これは、自動インクリメントキーに関連付けられたレベルがある場合は非常に手間がかかります。


あなたがここで述べた理由は、まさに私が私のstausesを保存するために別のテーブルを使っている理由です。私がこの質問をした主な理由は、より簡単なテキストフィールドを使用するのがよいかどうかを確認することです。
veganista

@Liamテキストフィールドに正規化される場合のみ。つまり、テキストフィールドが主キーのみに依存しており、主キーに基づいて物事を調べている場合、テキストフィールドが表示されます。リレーショナルDBはリレーションシップに関するものであり、ここに関係があるので、定義する必要があります。いくつかの例外の1つは、外部ソースからのダーティデータを処理しており、それを完全にモデル化する時間がない場合です。可能であればこれを避けてください。
スペンサーラスブン

目を隠し、決して戻らないGUIDを
む-sq33G

「リレーショナルデータベースの3つの理論」を書いておく必要があります。理論は常に実用的ではありません。多くの場合、関連するレコードにステータスコードを直接保存する方が効率的です。使用するために検索する必要がない場合は、別のテーブルへの結合を削除すると、多くの無駄な処理が節約されます。
Suncat2000

列タイプと全表スキャンの情報が間違っているため、ダウン投票。
イゴール

2

はい、PostStatusテーブルを持つオプション2を使用する必要があります。

他の回答に記載されているすべての利点は別として。

ステータスを追加または削除する必要があることに留意して、PostStatusテーブルに「有効」列を設定できます。そのため、ステータスが削除された場合、「有効」列に「N」のマークを付けると、ステータスを追加または削除すると、既存のレコードも問題なく残ります。


1

完全に正規化する場合、エンティティのステータスの変化は、実際には「statusChange」などの別のエンティティでモデル化されるという洞察に満ちた答えに追加したいと思います。

statusChangeエンティティとの追加の結合が必要になりますが、変更を実行するアクター、変更が発生した理由に関する可能なコメント、statusChangeが実行される日付、場合によっては有効になります。


0

レコードテーブルのステータスにテキストを使用することは、これが変更される可能性があり、挿入/更新のデータ整合性チェックを実行するのが難しいため、おそらく良い考えではありません。enumデータ型でDBMSを使用している場合は、代わりにこれを使用できます(パフォーマンスはおそらく低下しません...依存します)。

ステータスにメタデータ(説明、作成者、フレンドリ名など)が必要な場合は、ステータスを別のテーブルに保存し、レコードテーブルにステータスキーを保持する必要があります(必ず外部キーを使用してください)。idは必ずしも数字である必要はなく、ステータステーブルのPKだけです。また、ステータスが独自のテーブルにある場合、必要に応じてレコードタイプ(テーブル)間でステータスを共有できます。ステータステーブルへのJOINのパフォーマンスの問題については心配しません。

何をするにせよ、魔法のステータス(1はアクティブ、2は削除、...)を避けるようにしてください。これは、常に十分に大きなタイムラインで迷子になる傾向がある文書と伝統に依存しています。数値IDを使用している場合は、データベースのどこかにテキストの関連付けがあることを確認してください。


パフォーマンスについて心配していなければ、スケーラビリティを犠牲にしている可能性があります。コンピューターが魔法のステータスを回避することは不可能です。0と1は本質的に魔法です。
Suncat2000

0

データベース設計の目的に依存します。

アプリケーション(つまり、オブジェクト(コード)がすべてのマスター)をサポートするためだけにデータベースを設計する場合、列挙(またはそれらをサポートしないクラスの擬似列挙)を使用し、列挙の名前を格納するのは列挙型で許可される値を制御し、生データを強制的に表示するときにテーブルを少し読みやすくするので良い考えです(コードが実際にすべてを支配している場合はそうではありません)。ただし、列挙にフラグが立てられている場合。次に、通常は列挙値(整数)を保存します。


-1

ステータスは非常に重要です。投稿情報を取得するたびにステータスを取得する必要があるか、ステータスで投稿をフィルタリングする必要があります。別のテーブルにステータスがある場合、この情報を取得するには結合を行う必要があるため、パフォーマンスが低下します。間違いなく、同じテーブルにステータスがあるはずです。そして、それにインデックスを付けてください!ステータスとして整数を使用することも、列挙フィールドを使用することもできます。


-2

正しい解決策は、CQRSまたはブロックチェーンでイベントストア/ソースを使用することです。RDBでイベントをキャプチャする際の問題は、RDBが単一のイベントのスナップショットを時間内に保存することです。「ステータス/状態」などは、時間の経過とともに変化する一連の突然変異です。


私の投稿に賛成票を投じる場合は、ケースを作成してください。それ以外の場合は、ボックスの外側にほとんどスコープがないソフトマインドレミングです
-LastTribunal
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.