Mar*_*tus 6 sybase jdbc sybase-ase sybase-ase-15.7
我正在阅读Sybase ASE 15.7 文档中对datetime
数据类型的描述:
datetime 列包含 1753 年 1 月 1 日和 9999 年 12 月 31 日之间的日期。在支持此粒度级别的平台上,日期时间值精确到 1/300 秒。
我觉得上面的内容很混乱。首先,这是唯一添加了“在支持这种粒度级别的平台上”警告的数据类型。这究竟是什么意思,我如何确定我的平台是否是“支持这种粒度级别”的平台之一?
此外,我不清楚能够有效地准确存储 1/300 秒意味着什么。我正在使用 JDBC 访问数据库,其中唯一合理的类型是java.sql.Timestamp。这种类型允许我检索到纳秒的精度。但考虑到在一般情况下,除以 300 需要十进制系统中的无限位数,实际上需要小数纳秒(具有无限十进制数字)来保持表示为 1/300 秒的值。所以,这意味着我无法在不损失一些精度的情况下获取存储在服务器中的值,但可以忽略不计。
最后,当我执行以下查询时:
SELECT convert(char(32), submission_date, 139) FROM some..table
Run Code Online (Sandbox Code Playgroud)
我看到如下值:
Jan 6 2014 12:36:12.420000
Sep 12 2013 13:44:57.100000
Sep 10 2014 13:47:02.240000
Sep 10 2014 13:47:07.850000
Sep 10 2014 13:47:13.346000
Sep 10 2014 13:47:19.033000
Sep 10 2014 13:47:24.533000
Sep 10 2014 13:47:30.030000
Sep 10 2014 13:47:35.636000
Sep 10 2014 13:47:41.136000
Sep 10 2014 13:47:46.750000
Sep 10 2014 13:47:52.240000
Sep 25 2014 09:01:18.426000
Run Code Online (Sandbox Code Playgroud)
这些值似乎表明只保留了整整千分之一秒(而不是 1/300 秒——这需要千分之几)。如果服务器在内部存储值“精确到 1/300 秒”,我希望转换为十进制表示法以使用所有可用的小数位(3/300 秒、30/300 秒的边缘情况除外)秒、150/300 秒和其他一些不需要十进制系统中无限数量的数字)。
datetime
在 Adaptive Server Enterprise(和 SQL Server,因为它们共享一个包含 datetime 类型的公共代码库)中使用 8 个字节存储。4 个字节用于日期,4 个字节用于时间。您可以通过查看日期时间的二进制版本来看到这一点:
SELECT CONVERT(varbinary(8), CONVERT(datetime, '1753-01-01T00:00:00.000'), 0)
SELECT CONVERT(varbinary(8), CONVERT(datetime, '1900-01-01T00:00:00.000'), 0)
SELECT CONVERT(varbinary(8), CONVERT(datetime, '1900-01-02T00:00:00.000'), 0)
SELECT CONVERT(varbinary(8), CONVERT(datetime, '3000-12-31T23:59:59.997'), 0)
Run Code Online (Sandbox Code Playgroud)
四个二进制值是:
0xFFFF2E4600000000 0x0000000000000000 0x0000000100000000 0x000622D3018B81FF
下面是 1/300 秒发挥作用的地方:
SELECT CONVERT(varbinary(8), CONVERT(datetime, '1900-01-01T00:00:00.000'), 0)
SELECT CONVERT(varbinary(8), CONVERT(datetime, '1900-01-02T00:00:00.000'), 0)
SELECT CONVERT(varbinary(8), CONVERT(datetime, '1900-01-02T00:00:00.003'), 0)
Run Code Online (Sandbox Code Playgroud)
第二个和第三个值之间的差异是一:
0x0000000000000000 0x0000000100000000 0x0000000100000001
所以日期存储在最高有效的 4 个字节中;和时间存储在最低有效的 4 个字节中。尽管在 4 个字节的存储空间中移动到超过 3 毫秒(1/300 秒)的精度是可能的;这就是实际使用的所有精度。
在 SQL Server 中,您可以使用datetime2(7)
数据类型将精度降至 7 位,精度为 100ns:
SELECT CONVERT(varbinary(16), CONVERT(datetime2(7), '1900-01-01T00:00:00.0000000'), 0)
SELECT CONVERT(varbinary(16), CONVERT(datetime2(7), '1900-01-01T00:00:00.0000001'), 0)
SELECT CONVERT(varbinary(16), CONVERT(datetime2(7), '1900-01-01T00:00:00.0000002'), 0)
Run Code Online (Sandbox Code Playgroud)
这些值的存储略有不同,但您仍然可以看到二进制值递增:
0x0700000000005B950A 0x0701000000005B950A 0x0702000000005B950A
我正在使用 Sybase ISQL 客户端;Sybase CTISQL 实用程序/15.7/P-EBF20996 SP100/DRV.15.7.0.10
顺便说一句,Adaptive Server Enterprise (ASE) 和 SQL Server 舍入datetime
值的方式之间存在细微差别。在SQL Server中,毫秒四舍五入到0.000
,0.003
和0.007
,而在ASE他们四舍五入到0.000
,0.003
和0.006
-为什么是有区别的未记录,据我可以告诉。您可以通过运行以下查询在 ASE 上看到这一点:
SELECT CONVERT(varchar(50), CONVERT(datetime, N'2017-01-01T23:59:59.997'), 139);
Run Code Online (Sandbox Code Playgroud)
返回:
Jan 1 2017 23:59:59.996000
Run Code Online (Sandbox Code Playgroud)
而在 SQL Server 上,等效代码SELECT CONVERT(varchar(50), CONVERT(datetime, N'2017-01-01T23:59:59.997'), 109);
, 返回:
Jan 1 2017 11:59:59:997PM
Run Code Online (Sandbox Code Playgroud)