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 也表明 Ian 目前最喜欢的运动是壁球(因为它有最近的审计记录)。

我想知道对于这个简单的要求是否有更好的设计。

4

2 回答 2

1

没关系。这很好,事实上。

或者,您可以使用 AuditId 代替 Person 中的 SportId,作为对带有 current 的最新审计行的引用SportId,但这会使 Audit 成为当前表示的活动部分。我更喜欢您的设计,因为当前的表示仅限于较少的表,而审计表是一个支腿。它也更容易实现自动化——after update, delete在 Person 上的一个简单触发器将可靠地维护审计表,而无需任何人的进一步努力。

编辑

如果您不需要在审计表中记录当前关联,那么不要,并且您没有两次存储相同的信息。如前所述,一个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

您还可以删除该列Person.FavouriteSportID并在需要时查询最近的审计。保持数据一致更容易。

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

或者

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 回答