1

1つのマップにはN個の画像があります。ユーザーがマップデータを更新しても、古いデータが失われるため、更新は行いません。したがって、同じ自動インクリメントIDを使用してマップテーブルに挿入しますが、新しい日時スタンプを使用します。このようにして、ユーザーインターフェイスのマップ上のすべての変更を履歴に記録したいと思います。

テーブルマップ:PKはId+CreatedAtです

 [Id] [int] IDENTITY(1,1) NOT NULL, 
 [CreatedAt] [datetime] NOT NULL,   
 ...

テーブル画像:PKはId、FKはMapId + CreatedAt

[Id] [int] IDENTITY(1,1) NOT NULL,
[Image] [varbinary](max) NOT NULL,
[VisibleIndex] [int] NOT NULL,
[CreatedAt] [datetime] NOT NULL,
[MapId] [int] NOT NULL,

2つのフィールドを持つPKがある場合、FKにも2つのフィールドが必要です。

しかし、私の場合、これは機能しません。これは、テーブルImagesからのCreatedAt日付を、テーブルMapからのcreatedAt日付にすることができないためです。

過去の「更新」をどのように行いますか?

4

4 に答える 4

1

テーブルの主キーMapが単一の列Idである場合、テーブルの外部キーImagesは実際には、親テーブルMapIdの列を参照する単なる列です。Id

Mapテーブルの主キーが単一の列Idである場合、と同じ値を持つ別の行を挿入することはできませんId

IDENTITY列に指定された値の行を挿入することはできますが、ステートメントを実行するSET IDENTITY_INSERT tablename ON必要があり、次に対応するステートメントを実行することを忘れないでSET IDENTITY_INSERT tablename OFFください。


Mapテーブルの内容の履歴を取得するには、変更履歴を格納するための別の「MapHistory」テーブルを作成し、トリガーを使用してそれを維持することを検討します。

CREATE TABLE MapHistory (
[change_date] datetime NOT NULL,
[Id]          int      NOT NULL,
[CreatedAt]   datetime NOT NULL,
...

更新前の行の「履歴」を保存するには、トリガーでMap特別な論理deletedテーブルを参照できます。(完全を期すために、マップテーブルから行が削除されたときに履歴テーブルに行を保存することもあります。)

CREATE TRIGGER map_update ON Map AFTER UPDATE,DELETE AS
BEGIN
   SET NOCOUNT ON
   -- store column values as they existed prior to the update or delete
   INSERT MapHistory (change_date, Id, CreatedAt, ... )
   SELECT CURRDATE(), Id, CreatedAt, ... FROM deleted
END

このアプローチを使用すると、コードをはるかに簡単にすることができます。あなたがする必要があるUPDATEのはMapテーブルで実行することだけです、そしてデータベースはMapHistoryテーブルを維持することを引き受けます。

このアプローチのわずかな欠点の1つは、「現在の」値が1つのテーブルにあり、以前の値の履歴が別のテーブルにあることです。

現在の値もMapHistoryテーブルに保存したい場合は、代わりに起動するようにトリガーを変更し、AFTER INSERT, UPDATE代わりに特別な論理insertedテーブルを参照して、挿入された更新された行の「レプリカ」を履歴テーブルに作成することができます。

「古い」行と「新しい」行の両方を履歴テーブルに保存することもできますが、実際には冗長データを保存することになります。その場合、行が「削除済み」テーブルからのものか「挿入済み」テーブルからのものかを示す列を含めることをお勧めします。

CREATE TRIGGER map_update ON Map AFTER INSERT,UPDATE,DELETE AS
BEGIN
   SET NOCOUNT ON

   -- store column values as they existed prior to an update or delete
   INSERT MapHistory (source, change_date, Id, CreatedAt, ... )
   SELECT 'D', CURRDATE(), Id, CreatedAt, ... FROM deleted

   -- store column values as they exist after an update or insert
   INSERT MapHistory (source, change_date, Id, CreatedAt, ... )
   SELECT 'I' CURRDATE(), Id, CreatedAt, ... FROM inserted

END

補遺:

このアプローチにより、IdIDENTITYをMapテーブルの単純な主キーとして使用できます。change_date表に追加した列MapHistoryは冗長である可能性があり、そのCreatedAt列で意図した目的を果たしている可能性があります。

于 2012-06-28T20:45:49.913 に答える
0

マップの「一定」と「進化可能」の側面を2つのテーブルに分けます。

ここに画像の説明を入力してください

これは、マップフィールドのみをバージョン管理し、画像はバージョン管理しないことを前提としています。


イメージもバージョン管理する場合は、次のように実行できます。

ここに画像の説明を入力してください

新しいマップバージョンを作成する場合:

  • 変更されていない画像の場合:リンクをコピーするだけで、新しい画像バージョンを作成しないでください。
  • 変更された画像の場合:新しい画像バージョンリンクを作成します。

このように、地図が変更されたという理由だけで画像コンテンツの高価なコピーを行う必要はありません。新しいイメージバージョンを作成するのは、イメージ自体が変更された場合のみです。

注:このモデルは少し一般的すぎます。これにより、同じ画像を複数のマップ間で共有できます(同じマップの複数のバージョンだけではありません)。それを制限したい場合はお知らせください。


画像をマップに対して「プライベート」にするには、次のようにします。

ここに画像の説明を入力してください

代理キーを導入しないことに注意してください。代わりに、識別関係で「自然」キーを生成し、それをひし形の依存関係の下部でマージしImageLink.MapIdます。「ひし形」の両方の「エッジ」に外部キーがあります。

于 2012-06-28T21:14:56.193 に答える
0

キーだけでテーブルマップを作成できるように、実際の値を含むすべての最後の値を保持 する別のテーブル履歴を作成することをお勧めします。[Id] [int] IDENTITY(1,1) NOT NULL これは、トリガーまたはプロシージャを使用して行うことができ、日時を変更して履歴テーブルに現在のレコードを挿入し、レコードを更新する通常のマップテーブルに挿入します。

于 2012-06-28T21:10:37.297 に答える
0

古い親子関係を保持する場合の別の方法は、古いデータを新しい行に挿入してから、古い行を新しいデータに更新することです。トランザクション期間中の代理キーを除いて、2つのレコードが同じように存在することに影響を与える一意のインデックスまたはその他の制約がある場合は、3つの手順が必要になる場合があります。

于 2012-06-28T21:45:31.447 に答える