项目中由于需求设计,数据库中需要一个timestamp时间戳类型的字段来作为区别数据添加和修改的标识。由于timestamp在SQL SERVER 2005数据库中,不可为空的timestamp类型在语义上等同于binary(8)类型,可为空的 timestamp类型在语义上等同于varbinary(8)类型,这将导致在C#程序中获取到的timestamp类型则变成了byte[]类型。所以如果我们需要从数据库中获取并使用这个时间戳的话就必需经过转换。

我们先建立一张测试表,语句如下:

CREATE TABLE [dbo].[tb_Ts](
[id] [int] IDENTITY(1,1) NOT NULL,
[TS] [timestamp] NULL,
[text] [nvarchar](50) NULL
) ON [PRIMARY]

表名为tb_Ts,只有三个字段id,TS和text。其中TS字段就是我们需要的时间戳字段

SQL Server 中timestamp类型的定义

首先看下timestamp在SQL Server 2005中的定义,该定义摘抄自SQL Server 2005联机丛书(具体详情点击此链接):

timestamp 公开数据库中自动生成的唯一二进制数字的数据类型。timestamp 通常用作给表行加版本戳的机制。 存储大小为 8 个字节。 timestamp 数据类型只是递增的数字,不保留日期或时间。 若要记录日期或时间,请使用 datetime 数据类型。

备注:

每个数据库都有一个计数器,当对数据库中包含 timestamp 列的表执行插入或更新操作时,该计数器值就会增加。 该计数器是数据库时间戳。 这可以跟踪数据库内的相对时间,而不是时钟相关联的实际时间。 一个表只能有一个 timestamp 列。 每次修改或插入包含 timestamp 列的行时,就会在 timestamp 列中插入增量数据库时间戳值。 这一属性使 timestamp 列不适合作为键使用,尤其是不能作为主键使用。 对行的任何更新都会更改 timestamp 值,从而更改键值。 如果该列属于主键,那么旧的键值将无效,进而引用该旧值的外键也将不再有效。 如果该表在动态游标中引用,则所有更新均会更改游标中行的位置。 如果该列属于索引键,则对数据行的所有更新还将导致索引更新。

使用某一行中的 timestamp 列可以很容易地确定该行中的任何值自上次读取以后是否发生了更改。 如果对行进行了更改,就会更新该时间戳值。 如果没有对行进行更改,则该时间戳值将与以前读取该行时的时间戳值一致。 若要返回数据库的当前时间戳值,请使用@@DBTS

Transact-SQL timestamp 数据类型不同于在 SQL-2003 标准中定义的 timestamp 数据类型。 SQL-2003 timestamp 数据类型等同于 Transact-SQL datetime 数据类型。

rowversion 的数据类型为 timestamp 数据类型的同义词,并具有数据类型同义词的行为。 在 DDL 语句,请尽量使用 rowversion 而不是 timestamp。 有关详细信息,请参阅 数据类型同义词 (Transact-SQL)

程序中获取出的timestamp

如何使用SQL语句插入timestamp字段值?

我们从上面的timestamp定义中知道了timestamp这个值一般都是数据库自动添加和修改的,相当于自动增长标识一样(而且执行update修改语句这个字段也会自动更新),所以一般这个字段我们只做查询操作。如果要更新这个字段则会提示这个错误信息:不能更新时间戳列。但是这个字段是可以手动添加的,不过也只能使用DEFALUT字段(default字段为SQL Service数据库的一个默认值),如果传入其他值则会提示错误信息:不能将显式值插入时间戳列。请对列列表使用 INSERT 来排除时间戳列,或将 DEFAULT 插入时间戳列。下面是添加timestamp的SQL语句:

INSERT INTO [tb_Ts]([TS]) VALUES(DEFAULT)

解决数据库中timestamp类型和C#中byte[]类型转换问题

在程序中我们发现,通过ADO.NET获取数据库中timestamp字段值到程序中,结果类型为byte[]。假设在数据库中timestamp的值为0x00000000000007D6,那么获取到.net程序中的值就不是这样了,一把来说会变成byte[]的数组类型。那么我们的解决方式有两种,第一种方式是直接在数据库中将timestamp进行转换,可以转换成十六进制字符串类型或者BIGINT的长整形,这也是我推荐的方法。还有一种是在.NET 程序中使用BitConverter方法进行转换。以下是两种方式的代码:

方法一(在SQL中转换):
SELECT TS
,CAST(TS AS VARBINARY(8)) AS 'timestamp转十六进制字符串'
,CONVERT(BIGINT,TS) AS 'timestamp转bigint类型'
FROM tb_Ts

这样一来我们就可以获取到timestamp的十六进制字符串或者bigint,最终查询出来的结果如下图:

另外要说明的一点是,VARBINARY(8)对应的c# 类型是byte[],所以建议直接转换成bigint类型,否则在C#中还要调用下面的方法


方法二(在程序中转换,调用下面的方法即可):
/// <summary>
/// 将数据库中timespan转换成十六进制字符串
/// </summary>
/// <param name="objTs">从数据库中获取的timespan值</param>
/// <returns>timespan十六进制字符串</returns>
public string ConvertToTimeSpanString(object objTs)
{
byte[] btTsArray=objTs as byte[];
string strTimeSpan = "0x"+ BitConverter.ToString(btTsArray).Replace("-","");
return strTimeSpan;
}

timestamp 字段的更多相关文章

  1. C#更新SQLServer中的TimeStamp字段(时间戳) 防止同时修改一行时覆盖更新

    C#更新SQLServer中的TimeStamp字段(时间戳) 分类: C#2012-10-24 15:10 1878人阅读 评论(0) 收藏 举报 public partial class Form ...

  2. 批量更改int类型的timestamp字段to datetime

    批量更改int类型的timestamp字段to datetime 1.创建datetime字段created_at 2.update 字段 UPDATE table set created_at = ...

  3. mysql timestamp字段定义的

    Cause: java.sql.SQLException: Cannot convert value '2017-07-26 20:40:41.000000' from column 10 to TI ...

  4. mysql关于timestamp字段相关内容

    发现5.6和5.7版本的创建表不一致,从5.6导出数据表创建sql文件,然后导入到5.7表会报错,timestamp不能为空 查看的sql_mode mysql5.0以上支持的三种模式 1. ANSI ...

  5. oracle 将当前系统时间戳插入timestamp字段

    oracle 将当前系统时间戳插入timestamp字段 --insert records 精确到秒:insert into userlogin_his(usrname,logintime) valu ...

  6. mysql 5.5与5.6 timestamp 字段 DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP的区别

    http://www.111cn.net/database/mysql/55392.htm 本文章来给各位同学介绍关于mysql 5.5与5.6 timestamp 字段 DEFAULT CURREN ...

  7. Oracle的timestamp字段更新实验 结论:只有逐条更新才能保证timestamp字段有差别,批量更新只会得到一致的时间,此操作无关时间精度.

    有这么一张表: create table hy_testtime( id number(6,0) not null primary key, name nvarchar2(20) not null, ...

  8. 使用logstash读取MySQL数据传输到es,并且@timestamp字段采用MySQL中的字段时间--建议采用这个

    MySQL中数据样式 ES中数据样式 input { jdbc { jdbc_connection_string => "jdbc:mysql://192.168.0.145:3306 ...

  9. oracle中的timestamp字段的值乱码问题修改

    我的解决方案: 直接新增一个系统变量: key值为:NLS_TIMESTAMP_FORMATvalue的值为:YYYY-MM-DD HH24:MI:SSFF6 其它解决方案: 在登录PLSQL之后,查 ...

随机推荐

  1. thymeleaf标签使用方法总结

    https://blog.csdn.net/quuqu/article/details/52511933 常用th标签https://www.cnblogs.com/suncj/p/4030393.h ...

  2. flex 总结

  3. IntelliJ idea 备份与恢复

    为了防止突然断电或者电脑突然关机导致idea恢复出厂设置,需要定期备份配置. 一.备份 File---Export Settings 将settings.jar 文件导入到C:\Users\xutin ...

  4. EasyUI 通过 Combobox 实现 AutoComplete 效果

    朋友在做一个web程序,用的EasyUI框架,让我帮忙实现一个自动提示功能.由于之前我也没用过EasyUI框架,就想到了jQueryUI有 AutoComplete 插件,就想直接拿过来用. 但当我将 ...

  5. Java语法基础(四)----循环结构语句

    一.循环结构: 循环语句可以在满足循环条件的情况下,反复执行某一段代码,这段被重复执行的代码被称为循环体语句,当反复执行这个循环体时,需要在合适的时候把循环判断条件修改为false,从而结束循环,否则 ...

  6. Visual Studio Code配置Python环境

    安装环境python环境变量,这个就不写了,这类文章一抓一大把,这类就省略了······· 在Visal Studil Code中配置python环境,其实跟我的上一篇文章一样,如图: 这里有两个选择 ...

  7. Azure 门户中基于角色的访问控制入门

    面向安全的公司应侧重于向员工提供他们所需的确切权限. 权限过多,可能会向攻击者公开帐户. 权限太少意味着员工无法有效地完成其工作. Azure 基于角色的访问控制 (RBAC) 可通过为 Azure ...

  8. 64位的Sql Server使用OPENROWSET导入xlsx格式的excel数据的时候报错(转载)

    In the old times while all the CPUs were 32bit, we were happily using JET OLEDB Provider reaching Ex ...

  9. Java J2EE读取配置文件

    package com; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.naming.InitialCon ...

  10. SQL 时间戳转换为日期

    , '1970-01-01 00:00:00') 其中Timestamp为10位的时间戳,+8*3600是获取中国北京时间(东八区)