SQL利用Function建立長整形的唯一ID示例程式碼
前言
在設計表的時候考慮主鍵的資料型別是長整形還是字串,最簡單的方式當然是newid(),但這也有個問題,就是主鍵長度過長(36個字),資料量一多,必然會影響資料庫操作的效率,而且大大增加了資料檔案和索引檔案所佔用的空間。而且,newid返回的字串是隨機的,查詢結果不能保證按儲存順序返回。這對於有順序要求的系統來說,需要額外增加順序列來進行排序,這也導致查詢語句更加複雜。這也是主要放棄newid作為主鍵的主要原因。因此考慮用長整形來作資料表主鍵的資料型別。
實現方法
一開始在C#等面向對像語言中編寫一個獲取PK的方法,那是很順序就完成了。
接著是SQL中,如果要用指令碼匯入資料,那就要提供一個SQL的方法來獲取PK。
最初設計PK的組成:時間(yyMMddHHmmssmsS) + '4位隨機數' ,於是卡卡很快完成dbo.pk()
Create function dbo.pk() returns bigint as begin declare @pk as bigint,@fix bigint,@idx int,@ts as datetime set @ts = GETDATE() set @pk = convert(bigint,convert(varchar(6),@ts,12) + replace(convert(varchar(12),114),':',''))*10000 select @idx = A*10000 from vRand return (@pk + @idx) end go
然後來獲取一個10000PK測試:
declare @tab as table(pk bigint) declare @i as integer set @i =0 while(@i<10000) begin insert @tab select dbo.pk() set @i = @i+1 end select pk,count(1) cnt from @tab group by pk having COUNT(1)>1
oh my god!竟然有30多個重複的。
可見這個方法,做為獲取單個PK,那問題不大,但在做批量儲存的時候,可能會發生主鍵衝突。
因此再設計一個支援批量儲存的。
既然4位隨機數不能保證毫秒級的唯一,那就只能用有序數了,把PK的組成改為:時間(yyMMddHHmmssmsS) + '4位有序數'
再考慮到年份只是2位數,跟面向對像中的PK組成有機會在202x年之後存在衝突,因此增加一個標識 ‘1'+yy作為年以延長千年蟲問題,雖然還是有機會發生衝突,但那也是幾百年以後的事情了。
但是為了保持效率和衝突的概率,還是將PK改為:'1'+時間(yyMMddHHmmssms) + '4位有序數'.
接下來又是一頓卡卡卡,dbo.pks(@count)已出:
CREATE function dbo.pks(@count as int) returns @pks table(pk bigint,id int) as begin declare @pk as bigint,@ts as datetime,@lop int,@i int set @ts = GETDATE() set @pk = convert(bigint,'1'+convert(varchar(6),12) + replace(convert(varchar(11),''))*10000 set @idx =0 set @lop = CEILING(@count/10000.0) set @i = 1 while(@lop >0) begin set @pk = @pk + 10000 set @idx = 0 while(@idx<10000 and @idx<@count) begin insert @pks(pk,id) values(@pk+@idx,@idx+ @i) set @idx = @idx +1 end set @lop = @lop -1 set @i = @i+10000 end return end go
批量測試一下
select * from dbo.pks(500000)
正常返回500000行,沒有一行重複!
在返回的結果列中,ID是從1開始編號的,這也保持與SQL的Row_number保持一致,方便SQL程式設計引用。
OK,到這裡用利用SQL function獲取PK就搞定了!
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對我們的支援。