zoukankan      html  css  js  c++  java
  • 使用SQL生成DateTime.Ticks

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

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

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

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

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

    查看了 MSDN 上关于 DateTime.MinValueDateTime.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。

  • 相关阅读:
    ADODB.Recordset错误800a0cb3"的解决方
    C++ primer第一章 C++概述 纪要
    [收藏]一些电平转换方法
    “当传递具有已修改行的 DataRow 集合时,更新要求有效的 UpdateCommand”错误解决
    关于句柄的一些知识 Handle (computing) Wiki
    “/”应用程序中的服务器错误。当前标识(NT AUTHORITY/NETWORK SERVICE)没有对“C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/Temporary ASP.NET Files”的写访问权
    C++中 __stdcall,__cdecl, __fastcal区别简介
    [How To]使用Wildfish进行开发新Solution配置篇
    关于ISeries的代码生成器
    [How To]如何使用Wildfish进行ISeries项目开发数据库建立部分
  • 原文地址:https://www.cnblogs.com/gaochundong/p/generate_datetime_ticks_via_sql.html
Copyright © 2011-2022 走看看