テーブルの主キー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
補遺:
このアプローチにより、Id
IDENTITYをMap
テーブルの単純な主キーとして使用できます。change_date
表に追加した列MapHistory
は冗長である可能性があり、そのCreatedAt
列で意図した目的を果たしている可能性があります。