为了账号安全,请及时绑定邮箱和手机立即绑定

使用SQL生成DateTime.Ticks

标签:
SQL Server

在项目中我需要使用到一个随机数(Random Number),该随机数将作为 Hashtable 中的 Key 用于唯一索引数据,所以需要保持单机唯一性。

同时该随机数还需要具备可排序性以便对数据进行排序。

此时,我可以考虑使用随机字符串《C#生成MongoDB中的ObjectId》,这里的 ObjectId 具备单机唯一性和可排序性。

但另一个需求是,我需要该随机数为 int 或 long 类型,以便与依赖的 Service 进行通信,部分取代 TransactionId 或 Token 的职责。

所以,很自然的我就想到了时间。

查看了 MSDN 上关于 DateTime.MinValue 和 DateTime.Ticks 的定义,考虑到我所设计的服务每秒不会产生多于 10000000 的数据,

我决定使用 DateTime.Ticks 作为随机数的起始点,这样就有了下面这段代码。

复制代码

 1   public static class UniqueId 
 2   { 
 3     private static long _sequence = DateTime.UtcNow.Ticks; 
 4  
 5     public static long Generate() 
 6     { 
 7       return Interlocked.Increment(ref _sequence); 
 8     } 
 9 
 10     public static long Sequence
 11     {
 12       get
 13       {
 14         return _sequence;
 15       }
 16     }
 17   }

复制代码

业务逻辑中会将 UniqueId 存储到 SQL Server 数据库中,使用 bigint 类型进行存储。

1 CREATE TABLE [TableName](2     [UniqueId] [bigint] NOT NULL,3 );

这样,在数据库中,该 UniqueId 即可作为索引,也可进行排序。

现在问题来了,我需要将一个较老的服务升级到新的服务中,做 Date Migration。

老的服务中没有 UniqueId 逻辑和数据,这就需要我在数据迁移时为每条表数据生成该 UniqueId。

显然,SQL Server 不会帮我做这件事,我需要使用 SQL Script 来生成 UniqueId。

DateTime.Ticks 的定义是:

A single tick represents one hundred nanoseconds or one ten-millionth of a second. There are 10,000 ticks in a millisecond.

1 Tick 等于千万分之一秒,或万分之一毫秒。

The value represents the number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001, which represents DateTime.MinValue.

DateTime.Ticks 代表着从时间 "00:00:00.0000000, January 1, 0001" 至当前时间的 Tick 总数。

这样,我们就可以根据其原理通过 SQL 来计算其值。


 1 DECLARE @current_datetime DATETIME; 
 2 DECLARE @days_from_0001_to_1900 BIGINT; 
 3 DECLARE @ticks_per_millisecond BIGINT; 
 4 DECLARE @ticks_per_day BIGINT; 
 5 DECLARE @millisecond_of_time BIGINT; 
 6 DECLARE @ticks_of_days BIGINT; 
 7 DECLARE @ticks_of_time BIGINT; 
 8 DECLARE @ticks BIGINT; 
 9 
 10 SET @current_datetime = GETUTCDATE();
 11 SET @days_from_0001_to_1900 = 693595;
 12 SET @ticks_per_millisecond = 10000;
 13 SET @ticks_per_day = 24 * 3600 * 1000 * @ticks_per_millisecond;
 14 SET @millisecond_of_time = 
 15     DATEPART(MILLISECOND, @current_datetime) 
 16     + (DATEPART(SECOND, @current_datetime)) * 1000 
 17     + (DATEPART(MINUTE, @current_datetime)) * 60000 
 18     + (DATEPART(HOUR, @current_datetime)) * 3600000;
 19 SET @ticks_of_days = CAST(@days_from_0001_to_1900 + DATEDIFF(DAY, 0, @current_datetime) AS BIGINT) * @ticks_per_day;
 20 SET @ticks_of_time = @millisecond_of_time * @ticks_per_millisecond;
 21 SET @ticks = @ticks_of_days + @ticks_of_time;
 22 
 23 SELECT @current_datetime, @ticks


这段 SQL 脚本的运行结果是:

我们通过下面这段 C# 代码来验证结果。

复制代码

 1   class Program 
 2   { 
 3     static void Main(string[] args) 
 4     { 
 5       DateTime d1 = new DateTime(2014, 04, 01, 02, 52, 54, 153, DateTimeKind.Utc); 
 6       DateTime d2 = DateTime.Parse("2014-04-01 02:52:54.153"); 
 7       DateTime d3 = DateTime.Parse("2014-04-01 02:52:54.153", 
 8         CultureInfo.CurrentCulture, DateTimeStyles.AdjustToUniversal); 
 9 
 10       Console.WriteLine(d1.Ticks);
 11       Console.WriteLine(d2.Ticks);
 12       Console.WriteLine(d3.Ticks);
 13 
 14       Console.ReadKey();
 15     }
 16   }

复制代码

瞧,它们的结果一致为 635319175741530000。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消