Sybase 中神秘的“时间戳”数据类型是啥?

Posted

技术标签:

【中文标题】Sybase 中神秘的“时间戳”数据类型是啥?【英文标题】: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】:

最近有人问我是否可以将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 转换器来证明转换,如下所示:

http://www.fileformat.info/tip/java/date2millis.htm http://www.esqsoft.com/javascript_examples/date-to-epoch.htm

注意:对于 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 和 3 中使用 Sybase 的时间戳数据类型,而不是使用日期/时间。但在我看来,与使用 datetime 数据类型相比,它并没有为您节省很多工作。我想它可能会表现得更好。

【讨论】:

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

以上是关于Sybase 中神秘的“时间戳”数据类型是啥?的主要内容,如果未能解决你的问题,请参考以下文章

关于sybase的timestamp

sybase数据库的“like”用法是啥?

java时间戳是啥

Sybase,数据类型

sybase中如何查询前一天的数据

如何获取 sybase 表列名及其数据类型和顺序?