SQL Server数据库(时间戳timestamp)类型 (转载)

摘要:
时间戳描述公共数据库中自动生成的唯一二进制数的数据类型。这将导致在C#程序中获得的时间戳类型变为byte[]类型。时间戳数据类型最初是为了支持SQL Server恢复算法而实现的。@DBTS返回当前数据库使用的最后一个时间戳值。从上面的时间戳定义中我们知道,时间戳的值通常由数据库自动添加和修改。

timestamp介绍


  1. 公开数据库中自动生成的唯一二进制数字的数据类型。
  2. timestamp 通常用作给表行加版本戳的机制。
  3. 存储大小为 8 个字节。 不可为空的 timestamp 列在语义上等价于 binary(8) 列。可为空的 timestamp 列在语义上等价于 varbinary(8) 列。这将导致在C#程序中获取到的timestamp类型则变成了byte[]类型。所以如果我们需要从数据库中获取并使用这个时间戳的话就必需经过转换。
  4. timestamp 数据类型只是递增的数字,不保留日期或时间。 若要记录日期或时间,请使用 datetime 数据类型。
  5. 一个表只能有一个 timestamp 列。每次插入或更新包含 timestamp 列的行时,timestamp 列中的值均会更新。对行的任何更新都会更改 timestamp 值。
  6. 总结:SQL Server timestamp 数据类型与时间和日期无关。SQL Server timestamp 是二进制数字,它表明数据库中数据修改发生的相对顺序。实现 timestamp 数据类型最初是为了支持 SQL Server 恢复算法。每次修改页时,都会使用当前的 @@DBTS 值对其做一次标记,然后 @@DBTS 加1。这样做足以帮助恢复过程确定页修改的相对次序,但是 timestamp 值与时间没有任何关系。@@DBTS 返回当前数据库最后使用的时间戳值。插入或更新包含 timestamp 列的行时,将产生一个新的时间戳值。

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

首先我们创建一个带TIMESTAMP类型的表[tb_Ts]:

CREATE TABLE [tb_Ts]([TS] TIMESTAMP)

下面是添加timestamp的SQL语句:

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

我们可以将timestamp转换为十六进制或bigint,来方便进行比较和查看:

SELECT TS
,CAST(TS AS VARBINARY(8)) AS 'timestamp转十六进制' 
,CONVERT(BIGINT,TS) AS 'timestamp转bigint类型'
FROM tb_Ts
WHERE
CONVERT(BIGINT,TS)>=18004

结果:

SQL Server数据库(时间戳timestamp)类型 (转载)第1张

当然,我们也可以将bigint转换为timestamp类型,来进行比较:

DECLARE @TsValue BIGINT=82006

SELECT TS
,CAST(TS AS VARBINARY(8)) AS 'timestamp转十六进制' 
,CONVERT(BIGINT,TS) AS 'timestamp转bigint类型'
FROM tb_Ts
WHERE
TS<=CONVERT(TIMESTAMP,@TsValue)

或者:

DECLARE @TsValue BIGINT=82006
DECLARE @Ts TIMESTAMP=CONVERT(TIMESTAMP,@TsValue)

SELECT TS
,CAST(TS AS VARBINARY(8)) AS 'timestamp转十六进制' 
,CONVERT(BIGINT,TS) AS 'timestamp转bigint类型'
FROM tb_Ts
WHERE
TS<=@Ts

结果:

SQL Server数据库(时间戳timestamp)类型 (转载)第2张

时间戳字段在数据库中起什么作用:


1.给一个表加一个时间戳字段(timestamp),假设某条记录同时被两个人A和B读取并且正在修改。A先修改完成然后保存了,然后B再保存的时候,会由于时间戳不一致(因为A之前先保存修改了时间戳)导致B保存失败。timestamp是数据库记录版本控制的好东西,Linq to sql, entity framework都有很好的支持。

我们这里举一个EF Core的例子,假如我们在数据库中有一个表Book,它有一个timestamp类型的列TimeStampNumber,如下所示:

CREATE TABLE [dbo].[Book](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [BookCode] [nvarchar](20) NULL,
    [PersonCode] [nvarchar](20) NULL,
    [BookName] [nvarchar](50) NULL,
    [ISBN] [nvarchar](20) NULL,
    [TimeStampNumber] [timestamp] NULL,
 CONSTRAINT [PK_Book] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

我们用EF Core的DB First模式,将表Book映射为实体后,其生成的实体类Book如下:

public partial class Book
{
    public int Id { get; set; }
    public string BookCode { get; set; }
    public string PersonCode { get; set; }
    public string BookName { get; set; }
    public string Isbn { get; set; }
    public byte[] TimeStampNumber { get; set; }
}

可以看到数据库中timestamp类型的列TimeStampNumber,在EF Core中的确被映射为了byte[]类型。

我们还可以看看实体类Book的Fluent API如下:

modelBuilder.Entity<Book>(entity =>
{
    entity.Property(e => e.Id).HasColumnName("ID");

    entity.Property(e => e.BookCode).HasMaxLength(20);

    entity.Property(e => e.BookName).HasMaxLength(50);

    entity.Property(e => e.Isbn)
        .HasColumnName("ISBN")
        .HasMaxLength(20);

    entity.Property(e => e.PersonCode).HasMaxLength(20);

    entity.Property(e => e.TimeStampNumber).IsRowVersion();
});

可以看到EF Core用IsRowVersion方法对属性TimeStampNumber作了标识。

如何在C#中将byte[]类型转换为long类型,请查看这里

2.数据库优化:当在处理几十万条并发数据时,我们就可以在使用最频繁的表中添加一列字段,类型为timestamp,添加完毕后系统会自动生成相应的唯一值,如果数据记录有任何改动,timestamp值也会做相应的调整。

最近被这个时间戳虐到了,,,这几篇博文解释的很好,感谢博主
1.http://www.cnblogs.com/iampkm/p/4082916.html
2.http://www.cnblogs.com/windows/articles/2149701.html

原文链接

免责声明:文章转载自《SQL Server数据库(时间戳timestamp)类型 (转载)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇VC++-读取ini配置文件GetPrivateProfileStringlayer系列之弹层layer.prompt下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

SQL查询优化的方法 (转载)

大家都在讨论关于数据库优化方面的东东,刚好参与开发了一个数据仓库方面的项目,以下的一点东西算是数据库优化方面的学习+实战的一些心得体会了,拿出来大家共享。欢迎批评指正阿! SQL语句: 是对数据库(数据)进行操作的惟一途径; 消耗了70%~90%的数据库资源;独立于程序设计逻辑,相对于对程序源代码的优化,对SQL语句的优化在时间成本和风险上的代价都很低;...

一文看懂 MySQL 分区和分表,提高表增删改查效率

下载网站:www.SyncNavigator.CN客服QQ1793040---------------------------------------------------------- 关于HKROnline SyncNavigator 注册机价格的问题 HKROnline SyncNavigator 8.4.1 非破解版 注册机 授权激活教程 最...

[转]ORA00257解决

 原:http://blog.chinaunix.net/u/26381/showart_373304.html 从Oracle9i开始,借助于UNDO日志文件提供了闪回查询的功能,由于功能也有一定的局限性,也就是说依赖于UNDO日志的事务不能被覆盖,所以在Oracle10g开始又采用了一种新的FlashBack日志来实现这个功能,而且更为强大,可以将数据...

黑客入侵的常法

      1.无论什么站,无论什么语言,我要渗透,第一件事就是扫目录,最好一下扫出个上传点,直接上传 shell ,诸位不要笑,有时候你花很久搞一个站,最后发现有个现成的上传点,而且很容易猜到,不过这种情况发生在 asp 居多!    2.asp ( aspx )+MSSQL 先考虑注入,一般的注入都有 DBowner 权限可以直接写 shell ;如果...

linux系统tomcat部署SpringBoot+vue前后端分离项目正式部署

如果还没有安装jdk、mysql、tomcat可以先参考我的另一篇博客,linux系统tomcat部署SpringBoot+vue前后端分离项目准备工作 如果准备工作已经做完了,那么就开始正式部署吧。 上一篇仅仅安装成功了,既没有创建数据库,也没有导入数据,也没有将前后台文件放上来,接下来就一一进行操作。 上传数据库的sql文件,上传方式在上一篇博客中有详...

Mybatis查询在数据库中有但在代码中没有

代码是这样的: HashMap<String, Object> param = new HashMap<String, Object>(); param.put("ystJg", ystJg); List<xtglbm> ystjg = bd.getYstJg(param); Mapper是这样的 <select...