将所有贷款(插入贷款日期,更新退货日期)记录存储在一个表或2个表(带历史记录)中更好?

时间:2013-08-01 06:40:14

标签: sql sql-server database oracle

一个简单的数据库设计问题已经困扰了我一段时间,以为我会在这里问。

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

StudentIdentification, LoanDate, ReturnDate

此表用于跟踪已借出某些东西(不在数据库中)的每个学生。 由于每个学生都可以再次贷款和退还贷款(但不是多次贷款而不退货,贷款必须跟着退货),复合主键是

used: StudentIdentifcation and LoanDate

以这种方式存储数据或者有两个表是否更好

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

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

StudentIdentification

和LoanHistory表的主键是

StudentIdentification, LoanDate

每次学生返回时,“Loan”中的记录将被移至“LoanHistory”表,并且ReturnDate已更新(在交易中完成)。

哪个更好?

4 个答案:

答案 0 :(得分:1)

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

StudentIdentification, CreationDate, LoanDate, ReturnDate

前两列是PK。

您还可以添加金额来表示贷款或退货。

您可能会找到this question relvant

答案 1 :(得分:1)

使用三列的单个表是最简单的方法。它允许您回答诸如“2013年3月有多少学生借了东西?”之类的问题。容易。如果你有两个表,你需要访问它们来回答这个问题,因为你实际上有一个“开放贷款”和“退回贷款”表。

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

答案 2 :(得分: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需要这个模式,而这需要创建索引)

答案 3 :(得分:0)

提供准确答案更多信息。关于应用程序是必要的。例如,为什么没有一个包含StudentId和LoanDate的表,主键为StudentId。返回借出项目后删除该行。因此,没有StudentId记录,那么目前没有任何贷款。此建议假定LoanDate对于发送延迟提醒非常重要。如果不需要延迟提醒那么为什么甚至有LoanDate呢?

如果您需要包含退货日期和贷款日期的贷款历史记录。然后添加第二个历史记录表来存储行,因为它们将从贷款表中删除,并带有附加返回日期字段。