0

一个简单的数据库设计问题一直困扰着我,我想我会在这里问。

假设我有一个数据库表,"Loan"包含以下字段,

StudentIdentification, LoanDate, ReturnDate

该表用于跟踪每个借过东西的学生(不在数据库中)。由于每个学生都可以贷还贷再贷(但不能多次贷不还,贷后一定还贷),复合主键为

used: StudentIdentifcation and LoanDate

以这种方式存储数据还是使用 2 个表更好,

table 1: Loan   ( StudentIdentification, LoanDate)
table 2: LoanHistory   ( StudentIdentification, LoanDate, ReturnDate)

在这种情况下,贷款表的主键是

StudentIdentification

LoanHistory 表的主键是

StudentIdentification, LoanDate

每次学生返回时,“Loan”中的记录都会移动到“LoanHistory”表中,并更新 ReturnDate(在事务中完成)。

哪个更好?

4

4 回答 4

1

您可以使用简单的 SCD(缓慢变化维度)结构并使用一张表来存储当前和历史数据。

StudentIdentification, CreationDate, LoanDate, ReturnDate

前两列是PK。

您还可以添加金额以指示贷款或回报。

你可能会发现这个问题相关

于 2013-08-01T06:49:49.887 回答
1

拥有一个包含三列的表是最简单的方法。它允许您回答诸如“2013 年 3 月有多少学生借了东西?”之类的问题。容易地。如果您有两个表,则需要访问这两个表才能回答该问题,因为您实际上有一个“未结贷款”和“归还贷款”表。

可能是您的系统对当前开放的贷款非常感兴趣。它们可能会经常被查询和更新。在这种情况下,如果您将当前活跃的贷款放在一个表中,并且将历史记录推送到辅助表中,它会表现得更好。如果您需要保留大量历史但您很少阅读它,这很好。

于 2013-08-01T06:50:37.423 回答
1

我将创建一个表,然后有一个过滤索引(SQL Server 2008+)或索引视图(SQL Server 2005-)来强制每个学生只有一行NULL返回日期:

CREATE TABLE Loans (
    StudentID int not null,
    LoanDate datetime not null,
    ReturnDate datetime null,
    constraint PK_Loans PRIMARY KEY (StudentID,LoanDate),
    constraint CK_Loans_NoTimeTravel CHECK (LoanDate < ReturnDate)
)

过滤索引:

CREATE UNIQUE INDEX IX_Loans_SingleOpen ON Loans (StudentID) WHERE ReturnDate IS NULL

索引视图:

CREATE VIEW dbo.Loans_SingleOpen_DRI
WITH SCHEMABINDING
AS
    SELECT StudentID FROM dbo.Loans WHERE ReturnDate IS NULL
GO
CREATE UNIQUE CLUSTERED INDEX IX_Loans_SingleOpen ON Loans_SingleOpen_DRI (StudentID)

(假设dbo是适当的架构 - 需要SCHEMABINDING它,而创建索引又需要它)

于 2013-08-01T06:54:38.900 回答
0

要提供准确的答案,请提供更多信息。关于应用程序是需要的。例如,为什么不拥有一个具有 StudentId 和 LoanDate 的表,主键为 StudentId。当归还借出的项目时,删除该行。因此,没有 StudentId 记录,那么当前没有任何内容被借出。此建议假定 LoanDate 对于发送迟到的提醒很重要。如果不需要延迟提醒,那么为什么还要设置 LoanDate?

如果您需要贷款历史,包括归还日期和贷款日期。然后添加第二个历史表来存储行,因为它们从贷款表中删除,带有额外的返回日期字段。

于 2013-08-01T06:50:52.780 回答