查看: 129|回复: 2

SQL server进阶技能篇:说说MSSQL的时间戳

[复制链接]

4

主题

9

帖子

17

积分

新手上路

Rank: 1

积分
17
发表于 2023-1-1 19:59:41 | 显示全部楼层 |阅读模式
最近项目上正好遇到点关于SQL server时间戳的问题, 查了一下资料发现和原来意想中的不太一样,权且记录并分享。
问题的起因是这样的,有两个跨服务器的数据库DATA1 和DATA2 ,上面分别有表A和表B, 两个表中都有timestamp 类型的字段,假设都叫time。


现在想要用定时任务,实现当A表有更新时,即往B表中插入一条A表的数据,两表之间用id关联。本来我是这么写的:
insert into B (列1,列2,列3.......)

SELECT 列1,列2,列3....... FROM A

where  not exists (select 1 from B where  A.id=B.id )

or  exists (select 1 from A,

(select id,max(time) as timeB from  B group by B  ) C where A.id=C.id  and A.time>C.timeB
大致是这么个意思:从A表中取数据往B表里插,但满足两个条件之一:
(1)A里有B没有的,这就是第一个not exists 条件;
(2)A,B都有,但是A表记录的时间戳比B表最新的时间戳还要新的。
这么写完当时试了下没有问题,从A表里更新和新增的数据也都能插进去,
于是就挂成了定时任务。


第二天在查看数据的时候,发现数据量很大,感觉不对劲,于是仔细看了下,发现B表的重复数据挺多,很明显并非是A表真正的有频繁修改导致的。
经过定位分析,发现是time字段的问题。不管是什么样的情况下,A表的time字段始终大于B表的字段,所以导致脚本会一直执行。
我原本的理解时间戳字段,肯定是记录最新的更新次序,更新完B表后,时间戳肯定要大于A表的时间戳嘛,结果不是,于是搜了下,发现真是理解有误。
网上的资料是这么解释的:


也就是说,首先时间戳并不是时间也不能表示时间,它是一个二进制数字的类型,每次表记录更新时都会更新该列,因此它也确实可以用来比对数据是否被更新,但是要注意,它所表示 的是 相对次序,标黑了 :相对。
结合下面那段话,也就是说,是在同一个数据库里的相对次序,如果上面的例子中A和B表是在同一数据库,那是没有问题的。


于是用select @@DBTS在两个数据库里执行的结果,对比了一下发现真是不一样,也验证了我的想法,就是不同库对应的时间戳初始值是不一样的,所以没有可比性,比如DATA1中的时间戳都跑到1千万了,DATA2中才到100,那A表中的时间戳值可不是永远都比B表中的时间戳值大么?
好了,查到原因,就知道解决方法了,我想到两个方法:
(1)在DATA1库中建立表B,这样对比A和B的时间戳就有意义了;
(2)换个方式比对,在两个表中都加字段time2, 字段类型为datetime(),默认值getdate(),然后在判断的时候根据time2的时间来判断。
两个方法都可以实现,欢迎评论区讨论!
回复

使用道具 举报

4

主题

10

帖子

18

积分

新手上路

Rank: 1

积分
18
发表于 2023-1-1 20:00:23 | 显示全部楼层
怎么转换成时间
回复

使用道具 举报

0

主题

4

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2023-1-1 20:00:32 | 显示全部楼层
时间戳是数据库的流水序列号,不是时间,也不能转换成时间
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表