0

我有一个使用缓慢变化维度的数据仓库概念来跟踪旧版本的数据库表。所以,我用Log Trigger机制实现了它。

我的桌子是这样的:

CREATE TABLE "T_MyTable" (
    "Id" INT NOT NULL DEFAULT NULL,
    "Description" NVARCHAR(255) NULL DEFAULT NULL )

我创建了一个历史表

CREATE TABLE "T_MyTableHistory" (
    "Id" INT NOT NULL DEFAULT NULL,
    "Description" NVARCHAR(255) NULL DEFAULT NULL,
    StartDate DATETIME,
    EndDate   DATETIME )

然后,通过这样的触发器,我得到了历史:

CREATE TRIGGER TableTrigger ON T_MyTable FOR DELETE, INSERT, UPDATE AS

DECLARE @NOW DATETIME
SET @NOW = CURRENT_TIMESTAMP

UPDATE T_MyTableHistory
   SET EndDate = @now
  FROM T_MyTableHistory, DELETED
 WHERE T_MyTableHistory.Id = DELETED.Id
   AND T_MyTableHistory.EndDate IS NULL

INSERT INTO T_MyTableHistory (Id, Description, StartDate, EndDate)
SELECT Id, Description, @NOW, NULL
  FROM INSERTED

而且,要查询历史表,我使用

SELECT  Id, Description
    FROM T_MyTableHistory
    WHERE @DATE >= StartDate
    AND (@DATE < EndDate OR EndDate IS NULL)

现在,我的问题是:我的客户实际上只会按日期查询历史记录表(即没有一天中的时间),所以我需要获取那个日期的记录版本。我想到了两个选择:

  1. 更改触发器(如何?)每个日期只记录一个“历史”记录。

  2. 保持触发器原样,记录数据库中的所有更改(包括日期和时间),然后查询历史表以获取特定日期的最新版本(如何?)

我的感觉是第二个选项更容易实现,否则触发器可能会变得复杂(插入或更新,取决于当前日期的历史记录的存在)。

我需要一些帮助来选择正确的方向,并且我想在所选选项中提供所需的 SQL 查询示例。

4

2 回答 2

0

最后,我想出了这个查询:

SELECT Id, Description
    FROM T_MyTableHistory
    WHERE ( DateAdd(day, datediff(day,0, @MyDate), 0) >= StartDate ) AND 
    (( DateAdd(day, datediff(day,0, @MyDate), 0) < EndDate ) OR ( EndDate IS NULL ))

这应该比 varchar<->datetime 转换更快,并且它也应该与语言环境无关。顺便说一句,这个查询不需要 theTOP 1ORDER BY子句,因为函数

DateAdd(day, datediff(day,0, @MyDate)

自动返回选定的日期,带有“午夜”时间(例如 20141215 00:00:00),因此具有相同日期的记录会自动从结果中删除。

参考:

如何仅从 SQL Server 日期时间数据类型返回日期部分

在 SQL Server 中删除日期时间的时间部分的最佳方法

于 2014-12-15T08:16:32.813 回答
0

我同意你的第二种意见。最好将日期与时间一起保存。在基于日期过滤数据时使用 CONVERT()函数来确保只比较 DATE。此外,当客户输入单个日期时,如果记录具有相同的开始和结束日期,它们将不会出现在您的过滤器中,因此请使用 Date >= StartDate 和 Date <= EndDate not (>= ,<)

DECLARE @Date AS DATETIME
SET @Date = '2013-07-30'

SELECT TOP 1 Id, Description
    FROM T_MyTableHistory
    WHERE CONVERT(VARCHAR(20), @DATE, 103) 
       >= CONVERT(VARCHAR(20), StartDate, 103)
    AND (CONVERT(VARCHAR(20), @DATE, 103) 
       < CONVERT(VARCHAR(20), EndDate, 103) OR EndDate IS NULL)
    ORDER BY StartDate DESC
于 2014-12-11T11:13:07.103 回答