【问题标题】:What is the mysterious 'timestamp' datatype in Sybase?Sybase 中神秘的“时间戳”数据类型是什么?
【发布时间】:2011-03-30 20:46:33
【问题描述】:

我最近在我们的 Sybase 数据库中发现了一个使用“时间戳”类型的列的表。如果我像这样使用这种神秘的时间戳数据类型创建一个表

create table dropme (
    foo timestamp,  
    roo int null
)
insert into dropme (roo) values(123)
insert into dropme (roo) values(122)
insert into dropme (roo) values(121)
select * from dropme
go

我从 'select * from dropme' 中得到以下信息:

 foo                  roo
 -------------------- -----------
   0x000100000e1ce4ea         123
   0x000100000e1ce4ed         122
   0x000100000e1ce509         121

0x000100000e1ce4ea 在我看来不是很有时间戳。另外,我从“sp_help timestamp”看到了这个输出:

 Type_name Storage_type Length Prec Scale Nulls Default_name Rule_name Access_Rule_name Identity
 --------- ------------ ------ ---- ----- ----- ------------ --------- ---------------- ----------
 timestamp varbinary         8 NULL  NULL     1 NULL         NULL      NULL                   NULL

我的问题如下

  1. 什么是时间戳?
  2. 它与时间或日期有任何关系吗?
  3. 我可以将其转换为日期时间吗?
  4. 如果不是时间或日期,你用它做什么?

【问题讨论】:

    标签: sql sybase


    【解决方案1】:

    最近有人问我是否可以将TIMESTAMP SYBASE IQ数据类型转换为DATE;我一直避免使用这种数据类型,因为它是黑暗的。经过几个小时的阅读SYBASE documentation 并进行了一些测试,这是我的结论:

    时间戳:

    • 是一个 12 位的数字,存储为 BINARY(这可能会有所不同,具体取决于 环境)
    • 它表示自 1970 年 1 月 1 日以来以微秒为单位的值
    • Sybase 不包含用于转换它们的直接函数
    • 每次插入记录时都会自动建立

    这是将TIMESTAMP转换为DATE的SQL语句:

    SELECT timestamp as TS, CONVERT(decimal, timestamp) as TS_IN_MS,
       CONVERT(date, dateadd(SS, CONVERT(int, SUBSTRING(CONVERT(varchar,                     
          CONVERT(decimal, timestamp)), 1, 9)), '1/1/1970'), 123)  as TS_AS_DATE  
       FROM TheTable
    

    可以使用在线 EPOCH 转换器来证明转换,如下所示:

    注意:对于 SYBASE ASE,TIMESTAMP 类型不是有效的UNIX-EPOCH

    【讨论】:

    • 你的回答很好,除了一件事:关于 Sybase ASE 的陈述是错误的。查找 Unix Epoch(我的答案中的链接)。在您的代码中,您将 Unix 纪元 [1/1/1970](以 为单位)添加到 IQ TIMESTAMP,转换为秒。有用。在智商。好的。 Sybase ASE TIMESTAMP 以 毫秒 为单位。如果您为 ASE 编写相同的 SQL,考虑到这一点,它将起作用。试试吧。语句对于 SYBASE ASE,TIMESTAMP 类型不是有效的 UNIX-EPOCH。"false
    【解决方案2】:

    假设您将数据提取到您的应用程序。做完某件事后你想确保这条记录已经被改变,直到你得到(低级!)?

    在这种情况下,您应该有一个 TIMESTAMP 列。首先,您必须保存该列。在更新数据之前,您应该比较每个值以确保。

    这就是存在这种数据类型的原因!

    【讨论】:

      【解决方案3】:

      (这是一个作为单独问题Answers to the mysterious Sybase ASE 'timestamp' datatype questions 的用户发布的答案,没有代表在此处添加它。我已将其复制为社区 Wiki,因为我不想为此声明功劳,但它应该在这里)

      Q#1 的答案:“时间戳到底是什么?”

      • Sybase ASE 数据库的时间戳集中保存在该数据库的内部内存表“dbtable”中 - 该表是在数据库联机时构建的。您可以通过选择 @@dbts 查询当前 DB 时间戳 - 请注意,此 varbinary(8) 'Database' 时间戳值取决于平台,即受大字节序和小字节序的影响。

      • 每个用户表可能有一个时间戳列,用于保存给定行的插入/更新的“数据库”时间戳值。在成功完成 TSQL DML 命令时,所有“表”时间戳列值都由 ASE(就像标识列一样)自动维护。但是,与“数据库”时间戳不同,“表”时间戳值与平台无关,因为无论操作系统平台的字节顺序如何,它们始终以大端字节顺序保存(有关详细信息,请参阅下面的更多信息)。


      Q#2 的答案:“它与时间或日期有任何关系吗?”

      不,“数据库”时间戳和页面“本地”时间戳中的值不反映实际日期/时间。


      Q#3 的答案:“我可以将其转换为日期时间吗?”

      不,您不能将其页面的“数据库”时间戳或“本地”时间戳转换为日期/时间值。


      Q#4 的答案:'如果不是时间或日期,你用它做什么?'

      • 每当数据库中的页面被修改或创建时,“数据库”时间戳加一,而受影响页面的“本地”时间戳(在其页面标题内)随后与该点的“数据库”时间戳同步时间。

      • 与当前的“数据库”时间戳相比,数据库页面的“本地”时间戳反映了该页面上次更新或首次创建的相对年龄;因此,ASE 可以告诉数据库中所有页面的更新/创建的时间顺序。

      • 应用程序可以以与标识列类似的方式使用“表”时间戳列来查找最近或最近插入/更新的行,而不管行的键值如何。


      更多信息、警告和注意事项:-

      (1) “数据库”和“本地”时间戳存储在 3 个部分中,并且取决于操作系统平台的字节顺序。 例如0xHHHH 0000 LLLLLLLL

      • 2 字节高位 - 0xHHHH
      • 2 字节填充 - 0x0000
      • 4 字节低位 - 0xLLLLLLLL

      (2) 用户“表”时间戳也存储在 3 部分中,但始终是大端方向。 例如0x0000 HHHH LLLLLLLL

      • 2 字节填充 - 0x0000
      • 2 字节高位 - 0xHHHH
      • 4 字节低位 - 0xLLLLLLLL

      (3) 数据库时间戳保存在给定数据库的内存系统表 dbtable 中(该数据库在数据库上线时创建)。

      • 注 1 -“表”时间戳列值的保存方式与数据库表的数据和/或索引页中的其他列值一样,其中定义了时间戳列。
      • 注意 2 - 请注意,通过 SELECT @@dbts 查询当前数据库的“数据库”时间戳会返回其十六进制表示形式,该表示形式受操作系统平台的字节顺序限制。
      • 注 3 - 相反,通过 DBCC dbtable(不推荐)查询“数据库”时间戳会返回其 Big-endian 十六进制表示,因此,它与平台无关。
      • 警告 - 当给定数据库的“数据库”时间戳接近其最大限制时,即(0xFFFF,0xFFFFFFFF),可能需要十年或更长时间才能达到这一点,具体取决于数据库中插入/更新操作的频率, ASE 将发出警告,并且无法进行进一步的插入/更新 - 唯一的选择是使用 BCP(加上通过 sp_showtext 的存储过程)从所有对象中导出数据,删除数据库,再次创建它(使用新的 near-zer “数据库”时间戳)并导入数据(和存储过程)。

      仅供参考 - 以上答案、提示和技巧是真实准确的,因为我曾在 Sybase 工作,现在在拥有 ASE 产品的 SAP 工作。

      【讨论】:

        【解决方案4】:

        在 Sybase ASE 中,同一服务器中不同数据库的时间戳具有不同的值。

        使用数据库名称

        选择@@dbts

        因此很明显它与 Unix Epoch 或任何其他与时间相关的参考无关。

        它不同于 Sybase SQL Anywhere 的时间戳。

        【讨论】:

        • 看看你是否可以确定一个TIMESTAMP数据类型(问题)和@@DBTS之间的区别,文档告诉我的是数据库“时间戳”,这实际上是一个计数更改数据库中的页面。
        【解决方案5】:

        什么是时间戳?

        时间戳数据类型定义为

        varbinary(8) null
        

        它与时间或日期有任何关系吗?

        没有。这个名字选得不好。

        我可以将其转换为日期时间吗?

        没有。

        如果不是时间或日期,你用它做什么?

        每次插入或更新带有时间戳列的行时,时间戳列都会自动更新。请注意,实际上有两种时间戳。 TIMESTAMPCURRENT TIMESTAMP。区别在于CURRENT TIMESTAMP 只在插入时设置。

        Sybase documentation 停在那里,让我想知道为什么 f*rainbow!*k 有人会使用数据类型 timestamp。幸运的是,我找到了一些 other discussions 并推断了它在实现乐观并发控制时的用途。

        并发控制是一种确保多个事务可以同时/大约同时运行并且仍然产生正确数据的方法。 乐观并发控制是一种并发控制方法,它假设多个事务可以在不相互干扰的情况下完成。即不需要锁定。维基百科描述了以下算法:

        1. 记录交易开始时的日期/时间标记
        2. 读取/更新数据
        3. 检查其他事务是否修改了数据
        4. 提交或回滚

        可以在该算法的步骤 1 和 3 中使用 Sybase 的时间戳数据类型,而不是使用日期/时间。但在我看来,与使用 datetime 数据类型相比,它并没有为您节省很多工作。我想它可能会表现得更好。

        【讨论】:

        • 日期时间的分辨率不是那么大,它相对容易获得插入两个具有相同日期时间的行
        • 维基是可悲的。 Timestamp 是为 Optimistic Locking 而不是 OCC 而设计的,OCC 在编写 wiki 的业余爱好者之前就已经存在。上面给出的顺序是不正确的。另一个链接更好但没有解释OL。如果您打开一个新问题“什么是乐观锁定”,我会回答它。
        • @马克。真的。 DATETIME 的分辨率为 3 毫秒。但你的观点不适用于这里。在 Optimistic Locking 中(在这个答案中再次糟糕地解释了)相关的是客户端内存中的行(应用程序;存储过程;批处理;等)和服务器中的行之间的区别,这表明服务器中的行自获取以来已更新。使用DATETIME 列作为可读时间戳确实是标准做法。
        猜你喜欢
        • 2011-09-20
        • 2021-09-23
        • 2011-11-25
        • 2017-03-26
        • 2020-01-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多