淺談如何屏蔽數(shù)據(jù)庫(kù)中自增ID功能
在平時(shí)的項(xiàng)目開(kāi)發(fā)中,我相信有很大一批人都在用這個(gè)數(shù)據(jù)庫(kù)自增ID,用數(shù)據(jù)庫(kù)自增ID有利也有弊。
優(yōu)點(diǎn):節(jié)省時(shí)間,根本不用考慮怎么來(lái)標(biāo)識(shí)***記錄,寫程序也簡(jiǎn)單了,數(shù)據(jù)庫(kù)幫我們維護(hù)著這一批ID號(hào)。
缺點(diǎn):for example, 在做分布式數(shù)據(jù)庫(kù)時(shí),要求數(shù)據(jù)同步時(shí),這種自增ID就會(huì)出現(xiàn)嚴(yán)重的問(wèn)題,因?yàn)槟銦o(wú)法用該ID來(lái)***標(biāo)識(shí)記錄。同時(shí)在數(shù)據(jù)庫(kù)做移植時(shí),也會(huì)出現(xiàn)各種問(wèn)題,總之,對(duì)此自增ID有依賴的情況,都有可能出現(xiàn)問(wèn)題。我絕對(duì)相信園子里有很一部分人都被這個(gè)“好用的東西” 曾經(jīng)害慘過(guò)!
我平時(shí)在開(kāi)發(fā)項(xiàng)目的時(shí)候,一般都沒(méi)有用到數(shù)據(jù)庫(kù)的自增ID, 所以我想分享一下自己的解決方法。
解決思路
1:定義一張表,專門用來(lái)存放存所有需要***ID的表名稱以及該表當(dāng)前所使用到的ID值。
2: 寫一個(gè)存儲(chǔ)過(guò)程,專門用來(lái)在上一步的表中取ID值。
這個(gè)思路非常簡(jiǎn)單,我不作解釋了,直接來(lái)看看我的實(shí)現(xiàn)方法:
***步:創(chuàng)建表
- create table table_key
- (
- table_name varchar(50) not null primary key,
- key_value int not null
- )
第二步:創(chuàng)建存儲(chǔ)過(guò)程來(lái)取自增ID
- create procedure up_get_table_key
- (
- @table_name varchar(50),
- @key_value int output
- )
- as
- begin
- begin tran
- declare @key int
- --initialize the key with 1
- set @key=1
- --whether the specified table is exist
- if not exists(select table_name from table_key where table_name=@table_name)
- begin
- insert into table_key values(@table_name,@key) --default key vlaue:1
- end
- -- step increase
- else
- begin
- select @key=key_value from table_key with (nolock) where table_name=@table_name
- set @key=@key+1
- --update the key value by table name
- update table_key set key_value=@key where table_name=@table_name
- end
- --set ouput value
- set @key_value=@key
- --commit tran
- commit tran
- if @@error>0
- rollback tran
- end
對(duì)于在表中不存在記錄,直接返回一個(gè)默認(rèn)值為1的鍵值,同時(shí)插入該條記錄到table_key表中。而對(duì)于已存在的記錄,key值直接在原來(lái)的key基礎(chǔ)上加1.
總結(jié)一下,這種方法非常簡(jiǎn)單,我說(shuō)一下它的優(yōu)缺點(diǎn)。
優(yōu)點(diǎn):
1:ID值是可控的。用戶可以從指定段開(kāi)始分配ID值,這對(duì)于在分布式數(shù)據(jù)要求同數(shù)據(jù)同步時(shí),非常方便,很好地解決了ID重復(fù)的問(wèn)題。
2:在編寫程序中,ID值是可見(jiàn)的,比如在再插入關(guān)聯(lián)的記錄時(shí),相比使用數(shù)據(jù)庫(kù)自增ID的情況下,這種方法不需要在插入一條數(shù)據(jù)庫(kù)記錄之后,再去得到自增ID值,然再再使用該ID的值來(lái)插入關(guān)聯(lián)的記錄。我們可以一次性使用事務(wù)來(lái)插入關(guān)聯(lián)記錄。
3:對(duì)于需要批量插入數(shù)據(jù)時(shí),我們可以改寫一下上面的存儲(chǔ)過(guò)程,返回一個(gè)段的開(kāi)始ID,然后更新表時(shí)需要注意,不是原來(lái)的簡(jiǎn)單的遞增1,而是遞增你想要的插入多少條記錄的總數(shù)。
缺點(diǎn):
1:效率問(wèn)題,每次取ID值都需要調(diào)用存儲(chǔ)過(guò)程從數(shù)據(jù)庫(kù)中檢索一次。對(duì)于這種情況,我覺(jué)得效率不是很大問(wèn)題,因?yàn)镾QL server 會(huì)對(duì)我們經(jīng)常調(diào)用的存儲(chǔ)過(guò)程有緩存,再一點(diǎn),這個(gè)表的數(shù)據(jù)應(yīng)該不會(huì)很大,最多上千條(一個(gè)項(xiàng)目中上千個(gè)表的情況應(yīng)該不是很多吧)。所以檢索不是什么問(wèn)題,何況是根據(jù)表名來(lái)檢索(表名列已是主鍵)。
原文鏈接:http://www.cnblogs.com/repository/archive/2011/01/17/1937265.html
【編輯推薦】




























