代码之家  ›  专栏  ›  技术社区  ›  Dandikas

有没有方法从时间戳类型列中获取日期时间值?

  •  11
  • Dandikas  · 技术社区  · 16 年前

    我需要一个SELECT FROM表,该表没有列来告诉插入行的时间,仅 timestamp 列(值如:0x0000000000530278)。昨天有一些数据被导入到表中,现在我需要了解到底导入了什么:(

    有没有办法只用 时间戳 信息? Here 我发现:

    • 时间戳是一个8字节的十六进制序列号,与日期和时间都无关。
    • 要获取时间戳的当前值,请使用:@@dbts。

    也许有办法找到 时间戳 具体时间价值?这将有助于形成一个选择。或者有一个众所周知的解决方案?

    8 回复  |  直到 7 年前
        1
  •  19
  •   kristof    16 年前

    Transact-SQL时间戳数据类型是一种二进制数据类型,没有与时间相关的值。

    所以要回答你的问题: 有没有方法从时间戳类型列中获取日期时间值?

    答案是:

        2
  •  9
  •   Panagiotis Korros    16 年前

    SQL Server 2005中的timestamp数据类型是rowversion的同义词,它只是一个随着每行更新而自动递增的数字。

    您可以将其强制转换为bigint以查看其值。

    要获得新的或更新的行所需的内容,您应该适当地添加另一个日期时间列(lastupdate)和一个触发器,以便在每次更新时更新该列。

    对于过去已经插入的行,我认为您不能做些什么来找到确切的时间。

        3
  •  4
  •   evilhomer    16 年前

    恐怕无法将时间戳转换/转换为日期时间。 它们有完全不同的用途和实现,它们是不兼容的。

    看到这个链接 http://www.sqlteam.com/article/timestamps-vs-datetime-data-types

    网上图书也说 http://msdn.microsoft.com/en-us/library/aa260631.aspx

    SQL Server Timestamp数据类型具有 与时间和日期无关。SQL 服务器时间戳是二进制数 表示相对顺序 哪些数据修改发生在 数据库。时间戳数据类型 最初是为了支持 SQL Server恢复算法。

        4
  •  3
  •   kristof    16 年前

    另一个问题的答案是:

    如果时间戳列是您恢复的唯一资源(没有备份等),您可以尝试使用以下逻辑

    时间戳只是计数器的一个值,对于在包含时间戳列的表上执行的每个插入或更新操作,该值都递增。 .

    如果昨天发生的数据导入是几条记录中的一个插入,您可能会在时间戳列中看到一个数字序列,例如:

    0x00000000000007D1
    0x00000000000007D2
    0x00000000000007D3
    0x00000000000007D4
    0x00000000000007D5
    

    最新的序列可以是您添加的数据(当然不保证) 您可以将这些知识与其他东西(如使用自动增量列)结合起来,以标识您感兴趣的记录。

        5
  •  1
  •   ildanny    7 年前

    其他人正确地指出时间戳是一个二进制计数器。 不过,如果在数据库的任何表中,记录时间戳和日期时间,则可以使用该信息从任何时间戳转到日期范围。 为此,日志表是一个很好的候选者。假设您的导入表是“发票”,您可以使用如下查询:

    WITH TS 
    AS
    (
    SELECT 
        L1.LastDateUpdated, COALESCE(L2.LastDateUpdated, {TS '2099-12-31 00:00:00'}) as LastDateUpdatedTo,
        L1.[TIMESTAMP], L2.[TIMESTAMP] as [TIMESTAMPTo]
    FROM 
    (
        SELECT L1.[LastDateUpdated]
              ,L1.[TIMESTAMP]
              ,ROW_NUMBER() OVER (ORDER BY L1.[LastDateUpdated]) ID
        FROM [Log] L1
    ) L1
    left join 
    (
        SELECT L2.[LastDateUpdated]
              ,L2.[TIMESTAMP]
              ,ROW_NUMBER() OVER (ORDER BY L2.[LastDateUpdated]) ID
        FROM [Log] L2
    ) L2 
        ON L1.ID = L2.ID - 1
    )
    SELECT TS.LastDateUpdated, TS.LastDateUpdatedTo, * from [Invoices]
        inner join TS ON [Invoices].Timestamp between TS.Timestamp and 
    TS.TIMESTAMPTo
    ORDER BY TS.TIMESTAMPTo DESC
    
        6
  •  0
  •   Jonas Lincoln    16 年前

    我认为您最好的选择是从插入前还原备份,并将备份的表与当前表进行比较。

        7
  •  0
  •   ConcernedOfTunbridgeWells    16 年前

    要按时间戳标识新行,您需要跟踪预先存在的时间戳。在紧要关头,你可以:

    • 在其他地方还原以前的版本。
    • 将两个表中的数据复制到临时数据库中。
    • 从其中一个时间戳(而不是另一个时间戳)中标识插入的数据。

    如果数据库中还发生了其他事情,则存在轻微的误报风险,这将使您获得相当好的差异。

    对于更健壮的检查,您可以使用 Hashbytes 在行内容上给你一个非常低的碰撞概率的区别(参见维基百科上的这篇文章 Birthday attacks 关于这个问题的讨论)。

        8
  •  0
  •   Ashish Singh    10 年前

    我知道现在太迟了,但可能会帮助别人。

    timestamp/rowversion可以强制转换为bigint,但无论如何都不能与datetime进行比较。

    以下声明摘自msdn

    Transact-SQL rowversion 数据类型不是日期或时间数据类型。 时间戳 是的不推荐使用的同义词 划线 .

    有关更多详细信息,请参阅 here