Generate a unique time-based id on a table in SQL Server

前端 未结 2 1871
不知归路
不知归路 2020-12-22 08:42

I\'m trying to generate a unique id/timestamp based on the clock of the database server. This is not the main Id of the table, but it\'s in my interest that this value is un

相关标签:
2条回答
  • 2020-12-22 09:26

    Don't do it. Create a numerical identity column. For the most part, that will keep track of the order of inserts (this gets a little tricky in multi-threaded environments, but it should be close enough).

    Add another column, say createdAt with a default value of the timestamp. You can make this a datetime2 column for more precision.

    If you really need a unique numerical value, I would suggest creating a computed column whose type is something like decimal(38, 10). It would have a structure something like this: YYYYMMDDHHMMSSFFFFFF.. ("F" is for fractional seconds.)

    0 讨论(0)
  • 2020-12-22 09:31

    First, read all the excellent advice from the comments and other answers about why you probably should do something different.

    But, yes you can do this, and here's how. Basically just replace the last few digits of the datetime2 with the values from a sequence. The more digits you replace, the more rows you can insert at the same time without violating the unique constraint. In the example below I'm replacing everything past the 10th of a second with the sequence value. If you wanted to retain more digits of sub-second precision to store the actual clock time at which the insert was attempted, you would just reduce the maximum number of rows you can insert in a batch. So up to you.

    Here it is:

    drop table if exists MyTableWithUniqueDatetime2
    
    drop sequence if exists seq_ts_nanoseconds
    go
    create sequence seq_ts_nanoseconds
    start with 0 
    increment by 100
    minvalue 0
    maxvalue 99999900
    cycle
    
    go
    create or alter function GetTimestamp(@ts datetime2, @ns int)
    returns datetime2(7)
    as
    begin
     return  dateadd(ns,@ns, dateadd(ns,-(datepart(ns,@ts) % 100000),@ts))
    end
    go
    create table MyTableWithUniqueDatetime2
    (
      id bigint identity,
      a int,
      b int,
      ts datetime2(7) default dbo.GetTimestamp(sysdatetime(), (next value for seq_ts_nanoseconds)) unique
    
    )
    go
    select sysdatetime()
    insert into MyTableWithUniqueDatetime2 (a,b)
    output inserted.*
    select top (1000) 1,2
    from sys.objects o, sys.columns c, sys.columns c2
    
    0 讨论(0)
提交回复
热议问题