【问题标题】:SQL Server Convert Timestamp DataType to DecimalSQL Server 将时间戳数据类型转换为十进制
【发布时间】:2012-05-25 17:45:55
【问题描述】:

一直试图弄清楚这一点,并根据 MSDN 上的 Cast and Convert Documentation ,这应该是可能的( http://msdn.microsoft.com/en-us/library/ms187928.aspx)

查看转换表。

我正在运行以下代码:

CREATE TABLE TableName (
    ID bigint Identity(1,1),
    SomeValue nvarchar(20) not null,
    TimestampColumn timestamp not null)

Insert Into TableName (SomeValue)
values ('testing')

SELECT Convert(decimal, TimeStampColumn) from TableName

但是我只是收到以下错误:

将数据类型时间戳转换为数字时出错。

根据文档,这应该是可能的,还是我遗漏了什么? 请注意,我还需要转换回相同的时间戳值。

SELECT TimeStampColumn, Convert(timestamp, Convert(decimal, TimeStampColumn)) 
FROM TableName

最后上面的查询应该呈现相同的值。

【问题讨论】:

  • 您还应该考虑在Database Administrators 上提出这个问题 - 高级查询、数据库内部结构、数据库设计和所有其他与数据相关的问题都在那里讨论,并且信噪比非常高.
  • 我最初认为这与精度/比例有关,但不是来自我的测试。我不使用timestamp,但我很好奇原因。
  • @JNK 我也有同样的想法。但您输入的精度/比例无关紧要。二进制也应该转换为十进制,时间戳本质上是二进制(8)
  • @JohnHartsock 您的问题引起了人们的兴趣,也许还有些混乱。您介意用表定义更新我们吗?
  • @swasheck 使用表定义和插入语句更新了问题。

标签: sql-server sql-server-2008 tsql


【解决方案1】:

试试这个;虽然 MSDN 说这是一种隐式转换,但它实际上不起作用。所以,我正在做的是将其转换为 INT,然后转换为十进制(无论如何,INT 到十进制都是隐式的)

select val, CAST((CONVERT(bigint, timestampcol)) as decimal) as 'TS as decimal' 
from teststmp

【讨论】:

  • OP需要直接转换为DECIMAL来处理超出intbigint范围的值
  • @JNK - 为什么? timestamp 只有 8 个字节(与 bigint 相同)
  • @JohnHartsock - So same as bigint then
  • @Rahul 是的,在“堆”中与其他人交谈,我们得出了相同的结论。 + 1 个最佳解决方案。
  • @JohnHartsock - 不确定您使用它的目的是什么,但我的测试表明它实际上被视为无符号 64 位整数,而不是像 bigint 那样有符号。所以在9,223,372,036,854,775,807之后分配的timestamp就是-9,223,372,036,854,775,808
【解决方案2】:

我认为这是一种更安全的方式。

SELECT CASE 
         WHEN Cast(timestampcol AS BIGINT) >= 0 THEN 
         Cast(timestampcol AS BIGINT) 
         ELSE 18446744073709551615 + Cast(timestampcol AS BIGINT)
       END 

以下内容表明,否则直接转换为 bigint 将环绕为负数,这可能不是所需的结果。

USE tempdb;

IF DB_ID('TestDBTS') IS NOT NULL
    DROP DATABASE TestDBTS;

CREATE DATABASE TestDBTS;


USE TestDBTS;

SELECT CAST(CAST(@@DBTS AS BIGINT) AS DECIMAL(20,0))
/*2000*/

/*Hack to manually set the timestamp. Undocumented, Unguaranteed & Dangerous!
  Do not use except on test databases.*/
DBCC WRITEPAGE(TestDBTS, 1, 9, 412, 8, 0xFFFFFFFFFFFFFF7F);


ALTER DATABASE TestDBTS SET OFFLINE WITH ROLLBACK IMMEDIATE;

ALTER DATABASE TestDBTS SET ONLINE WITH ROLLBACK IMMEDIATE;

USE TestDBTS;
SELECT CAST(CAST(@@DBTS AS BIGINT) AS DECIMAL(20,0))
/*9223372036854775807*/

CREATE TABLE T
(
X INT,
Y TIMESTAMP
)

INSERT INTO T(X) VALUES(1)

SELECT CAST(CAST(@@DBTS AS BIGINT) AS DECIMAL(20,0))
/*-9223372036854775807*/

SELECT CASE WHEN CAST(@@DBTS AS BIGINT) >= 0 
            THEN CAST(@@DBTS AS BIGINT)
            ELSE 18446744073709551615 + CAST(@@DBTS AS BIGINT) 
       END
/*9223372036854775808*/

【讨论】:

    【解决方案3】:

    试试这个:

    SELECT CONVERT(decimal, TimeStampColumn + 0)
    FROM TableName
    

    【讨论】:

    • 不会隐式转换为INT吗?
    • 关闭但仍不存在。我无法转换回相同的时间戳值。
    猜你喜欢
    • 1970-01-01
    • 2015-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多