0

以下の DDL をご覧ください。

CREATE TABLE Sport (ID int, Description varchar(50),primary key(ID))

CREATE TABLE Audit (AditID int, PersonID int, SportID int, AuditDate datetime,primary key(id))

CREATE Table Person (ID int not null, Name varchar(50), FavouriteSportID int, PRIMARY KEY (id),
FOREIGN KEY (FavouriteSportID) REFERENCES Sport(Id))

INSERT INTO Sport VALUES (1,'Football')
INSERT INTO Sport VALUES (2,'Basketball')
INSERT INTO Sport VALUES (3,'Squash')

INSERT INTO Person VALUES (1,'Ian',1)
INSERT INTO Audit VALUES (1,1,1,'2012-01-01')
INSERT INTO Audit VALUES (2,1,1,'2012-02-01')
INSERT INTO Audit VALUES (3,1,'2012-03-01')

監査テーブルには、個人が過去に好きだったスポーツが表示されます。

これには、Person.FavouriteSportID と最新の監査レコード (監査レコード ID 3) の 2 つの場所にお気に入りのスポーツを保存する必要があることを認識しています (監査レコードが最新であるため)。

この単純な要件に対してより良い設計があるかどうか疑問に思っています。

4

2 に答える 2

1

大丈夫だよ。実際、それは良いことです。

または、SportId in Personの代わりにAuditIdを使用して、現在の最新の監査行への参照として使用することもできSportIdますが、これにより、Auditは現在の表現のアクティブな部分になります。現在の表現は少数のテーブルに限定されており、監査テーブルはアウトリガーであるため、私はあなたのデザインの方が好きです。また、自動化もはるかに簡単です。Personをafter update, deleteトリガーするだけで、誰もそれ以上の労力をかけることなく、監査テーブルを確実に維持できます。

編集

現在の関連付けを監査テーブルに記録する必要がない場合は、記録しないでください。同じ情報を2回保存していません。述べたようにafter update, delete trigger

-- syntax assuming SQL Server 2008+, adapt as appropriate
create trigger tr_Person_Audit on Person 
after update, delete 
as begin
  insert Audit (PersonId, SportId, ExpirationDate)
  select PersonId, SportId, getdate() -- as expiration date
  from (
    select PersonId, SportId from deleted except 
    select PersonId, SportId from inserted -- control for updates where nothing changed
    ) this
end

現在の関連付けを監査テーブルに記録する必要がある場合、それはそれほどクリーンではありませんAuditが、それでもアウトリガーであり、after insert, updateトリガーを使用して自動化できます。

-- syntax assuming SQL Server 2008+, adapt as appropriate
create trigger tr_Person_Audit on Person 
after insert, update
as begin
  insert Audit (PersonId, SportId, EffectiveDate)
  select PersonId, SportId, getdate() -- as effective date
  from (
    select PersonId, SportId from inserted except  
    select PersonId, SportId from deleted -- control for updates where nothing changed
    ) this
end
于 2012-12-09T22:46:06.113 に答える
0

You could also drop the column Person.FavouriteSportID and query the most recent audit when you need it. It's easier to keep the data consistent.

SELECT TOP 1 SportID
FROM Audit
WHERE PersonID = @1
ORDER BY AuditDate DESC

Or

SELECT
    Person.*,
    (SELECT TOP 1 Audit.SportID
     FROM Audit
     WHERE Audit.PersonID = Person.PersonID
     ORDER BY Audit.AuditDate DESC) AS FavouriteSportID
FROM
    Person
于 2012-12-10T01:48:57.640 に答える