2011 年 1 月 1 日改訂
わかりましたので、私が座っている場所 (完全に監査可能なデータベースを提供します。あなたのデータベースはその特定の要件です) とあなたが座っている場所 (質問とコメントに基づく) の間にはギャップがあります。これについては、おそらく解説で解決します。ここからスタート地点です。
この要件を満たすために、次のものはまったく必要ありません。大量複製; 壊れた整合性; 等
これも古典的な時間要件ではないため、「期間」機能は必要ありませんが、可能です。
ValidFromとValidTo は正規化エラーです。ValidTo は簡単に導出できるデータです。次の行の ValidFrom で、任意の行の ValidTo が複製されます。更新異常があります (ある行の 1 つの列を更新すると、次の行の他の列も更新する必要があります)。「現在」にはダミーの値を使用する必要があります。
これらはすべて、ユーザーがシステム内で編集可能であり、削除可能です。
うーん、ダメ。重要な情報を保持するデータベースです。スクラッチパッドではなく参照整合性を使用するため、ユーザーはそこまで歩いて何かを「削除」することはできません。これは、履歴データを維持するという同じユーザー要件 (Reading; Alert; Ack; Action; Download) と矛盾します。
カスケード削除は許可されていません。これらの機能は、データベース以外の MS Access タイプのチェック ボックスです。実際のデータベースの場合、RI 制約により、子を持つ親が削除されなくなります。
主キーは変更できません (すべきではありません)。例えば。ユーザーID; LocationId; NetworkSlaveCode は変更されません。これらは慎重にIdentifiersと見なされることに注意してください。PK の特徴の 1 つは、安定していることです。
新しいユーザーを追加できます。現在のユーザーの名前を変更できます。ただし、Download、Acknowledgement、Action にエントリがあるユーザーは削除できません。
基本的に、編集可能な場合は、履歴である必要があります (つまり、測定値とアラートは除外されます)。
また除外: ダウンロード; 謝辞; 行動。
参照テーブル: SensorType; AlertType; アクションタイプ。
新しい履歴テーブル: 挿入されますが、更新または削除することはできません。
isObselete フラグで私が見つけた問題は.. Location を変更すると、Sensor の外部キーが廃止されたレコードを指すようになり、すべてのセンサー レコードを複製する必要があるとします。この問題は、階層が大きくなるにつれて指数関数的に悪化します。
わかりました。では、LocationId
(FK) inSensor
は変更されないことを理解していますか。大量重複などはありませんか?そもそも問題はありません (そして、あのばかげた本には問題があります!) が、2 番目に指数関数的に悪化します。
IsObsolete
あなたの要件には不十分です。(下記参照)
UpdatedDtm
実際の行 (などReading
) は、その時点で有効だった親 (FK からSensor
) の履歴行 (そのAuditedDtm
) を識別します。
完全なリレーショナル機能。宣言的参照整合性など
IDEF1X、強力な識別子の関係概念を維持します...現在の親行は1つだけです(例:場所)
履歴の行は、変更前の現在の行のイメージですAuditedDtm
。現在の行 (非履歴) は、行が変更された最後の UpdatedDtm を示します。
は、特定のキーの一連のAuditedDtm
全体を示しています。UpdatedDtms
したがって、私はそれを使用して、時間的な意味で実際のキーを「分割」しました。
必要なのは、変更可能な各テーブルの履歴テーブルだけです。4 つの識別テーブルの Hiistory テーブルを用意しました。センサー; NetworkSlave; およびユーザー。
会計の意味で Auditableを理解するために、これをお読みください。
データ・モデル
履歴を含むセンサー データ モデルへのリンク(ページ 2 には、履歴テーブルとコンテキストが含まれています)。
Relational Modeling Standard に慣れていない読者には、IDEF1X 表記法が役立つかもしれません。
コメントへの対応
(1)私の最初の問題は、履歴データとの参照整合性の問題です。存在するかどうかはわかりません。存在する場合、それがどのように機能するかはわかりません。たとえば、SensoryHistory では、場所自体が存在する前の日時を示す UpdatedDtm を持つレコードを追加することができます。これが実際に問題であるかどうかはわかりません-それを強制するのはやり過ぎかもしれません。
(他の質問でも同様の問題を提起しました。)経験したデータベースには、実際には参照整合性が設定されていなかった可能性があります。Relation 行はドキュメントのためだけに存在していたこと。RI が「アプリ コードに実装されている」こと (つまり、RI がないことを意味します)。
これは ISO/IEC/ANSI 標準 SQL データベースです。これにより、宣言的な参照整合性が可能になります。すべての関係行は、宣言された実際の制約である PK::FK 参照として実装されます。例えば:
CREATE TABLE Location
...
CONSTRAINT UC_PK
PRIMARY KEY (LocationId)
...
CREATE TABLE Sensor
...
CONSTRAINT UC_PK
PRIMARY KEY (LocationId, SensorNo)
CONSTRAINT Location_Sensor_fk
FOREIGN KEY (LocationId)
REEFERENCES Location(LocationId)
...
CREATE TABLE SensorHistory
...
CONSTRAINT UC_PK
PRIMARY KEY (LocationId, SensorNo, UpdatedDtm))
CONSTRAINT Sensor_SensorHistory_fk
FOREIGN KEY (LocationId, SensorNo)
REEFERENCES Sensor (LocationId, SensorNo)
...
これらの宣言された制約は、サーバーによって強制されます。トリガー経由ではありません。アプリコードではありません。つまり、次のことを意味します。
- に存在しない
Sensor
a を持つAは挿入できません LocationId
Location
- に行がある は
LocationId
削除できません Location
Sensor
- に存在しない
SensorHistory
a を持つAは挿入できません LocationId+SensorNo
Sensor
- に行がある は
LocationId+SensorNo
削除できません。 Sensor
SensorHistory
(1.1)すべての列には、値の範囲を制限するための RULE と CHECK 制約が必要です。すべての INSERT/UPDATE/DELETE がストアド プロシージャ内でプログラムによって実行されるという事実に加えて、したがって事故は発生せず、人々はデータベースに近づいてデータベースに対してコマンドを実行することはありません (SELECTS を除く)。
一般的に、私はトリガーから離れています。ストアド プロシージャと通常のアクセス許可を使用している場合は、次のようになります。
SensoryHistory では、場所自体が存在する前の日時を示す UpdatedDtm を持つレコードを追加することができます。
防止されます。センサー自体よりも前に UpdatedDtm を使用して SensorHistory を挿入することも同様です。しかし、proc は宣言型ルールではありません。ただし、二重に確実にしたい場合 (つまり、INSERTS はすべてユーザーによる直接コマンドである proc を介して行われるため)、確実にトリガーを使用する必要があります。私にとって、それは最高です。
(2)削除を示すにはどうすればよいですか? 私が推測するテーブルの非歴史的なバージョンにフラグを追加するだけで済みます。
まだ確かではない。例えば。a が削除されると最終的なものになることを受け入れますかSensor
... (はい、履歴は維持されます) ... そして、新しいSensor
が に追加されるとLocation
、新しいものになります ...で論理的に置き換えられるSensorNo
ことはありませんSensor
時間のギャップの有無にかかわらず、新しいもの?
エンドユーザーの観点から見ると、ソフトウェアを介して、センサーを制限なく自由に追加、編集、および削除できる必要があります。ただし、一度削除すると削除され、元に戻すことはできません。まったく同じパラメーターを使用しても、後でセンサーを再度追加するのを止めるものは何もありません。
そして「削除」Locations, NetworkSlaves
、そしてUsers
同様に。
Ok。次に、Sensor
同じパラメーターを持つ new は真に新しく、 new を持ち、SensorNo
以前の論理から独立していますSensor
。IsObsolete
4 つの識別テーブルに BOOLEAN を追加できます。現在、適切であると識別されています。削除はソフト削除になりました。
(2.1)NetworkSensor
とLoggerSensor
は、実際には 2 つの親に依存しています。どちらかの親が廃止された場合、それらは廃止されます。したがってIsObsolete
、該当する親から派生できる二重の意味を持つ列を指定しても意味がありません。
(2.2) 明確にするために、ユーザーはトランザクション テーブルと履歴テーブルから行を削除することはできませんよね?
(3)表を更新する場合、履歴表に新しい行を挿入して主表を更新するには、どのような方法が最適ですか? トランザクション内の通常の SQL ステートメントだけでしょうか?
はい。ACID プロパティによると、これはトランザクションの古典的な使用法であり、アトミックです。toto で成功するか、toto で失敗します (後で問題が修正されたときに再試行されます)。
(4) 参考図書
決定的で影響力のあるテキストは、Temporal Data and the Relational Model CJ Date、H Darwen、NA Lorentzos です。同様に、RM を採用している私たちは、拡張機能と、RM の後継に必要なものに精通しています。他の方法ではなく。
参照された本は恐ろしく、無料です。PDF は PDF ではありません (検索なし、インデックス作成なし)。私のMSとオラクルを開くとわかります。たくさんの毛羽立ちに包まれたいくつかの良いビット。多くの虚偽表示。詳細に回答する価値はありません (適切なレビューが必要な場合は、新しい質問を開いてください)。
(4.1)ValidTo
に加えてValidFrom
。本が犯す重大な間違い(私の回答の上部で特定されているように)。その後、苦労して解決します。そもそも間違いを犯してはいけません.2番目に解決するものは何もありません. 私が理解しているように、それはあなたのトリガーを排除します.
(4.2) 正規化と一時的な要件の両方を考慮した単純なルール。何よりもまず、(a) 一時的な要件と (b) DataTypes、正しい使用法と制限を深く理解する必要があります。常に保存:
(4.3) それらは「一時的な主キー」をいじり、コードを複雑にします (更新異常を制御するためのトリガーが必要になることに加えて)。私はすでにクリーンな (試行錯誤した) テンポラル主キーを提供しました。
(4.4) ダミー値、非実数値、および「現在」の Null をいじります。私はデータベースでそのようなことを許可しません。重複ValidTo
した を保存していないので、問題はありません。解決するものは何もありません。
(4.5) なぜ 528 ページの「テキストブック」が Web 上で無料で入手できるのか、質の悪い PDF 形式であることに疑問を抱かざるを得ません。
(5)私 [ユーザー] は、たとえば、すべての LocationHistory 行を黙って喜んで削除できます (現在のバージョンのみを Location テーブルに残します)。それが理にかなっていれば、場所。
私には意味がありません。私たちが埋めなければならないコミュニケーションにはまだギャップがあります。閉店までお付き合いください。
(6)DMの誤字を1箇所修正。AnAlert
はReading
ではなくの表現ですSensor
。
(7) それを反映するために、他の質問/回答のビジネス ルールを修正しました。そして、この質問で明らかになった新しいルール。
(8) IDEF1X に完全に準拠したモデルがあるため、識別子を再定義することを理解していますか?
識別子はデータベース全体に渡され、その力を保持します。例えば。リストするときは、 and でAcknowledgements
直接結合できます。中間のテーブルを読み取る必要はありません (キーが使用されている場合は読み取る必要があります)。これが、実際には、リレーショナル データベースで必要な結合が少ない (そして正規化されていないデータベースで必要な結合が多い) 理由です。Location
Sensor
Id
サブタイプなどは、その特定のコンテキストが関連する場合にのみナビゲートする必要があります。