国产高清在线免费观看-国产高清在线免费无码-国产高清在线男人的天堂-国产高清在线视频-国产高清在线视频精品视频-国产高清在线视频伊甸园

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

SQL Server中流水號生成的注意事項(xiàng)

admin
2011年3月3日 17:14 本文熱度 3898

  前幾天一個(gè)人問到了關(guān)于流水號重復(fù)的問題,我想了下,雖然說這個(gè)問題比較簡單,但是具有廣泛性,所以寫了這篇博客來介紹下,希望對大家有所幫助。

  在進(jìn)行數(shù)據(jù)庫應(yīng)用開發(fā)時(shí)經(jīng)常會(huì)遇到生成流水號的情況,比如說做了一個(gè)訂單模塊,要求訂單號是唯一的,規(guī)則是:下訂單時(shí)的年月日+6位的流水號這樣的規(guī)則。

  對于這種要生成流水號的系統(tǒng),我們一般是在數(shù)據(jù)庫中新建了一個(gè)種子表,每次生成新的訂單時(shí):

  1.讀取當(dāng)天種子最大值。

  2.根據(jù)種子最大值和當(dāng)時(shí)的年月日生成唯一的訂單號。

  3.更新種子最大值,使最大值+1。

  4.根據(jù)生成的訂單號將訂單數(shù)據(jù)插入到訂單表中。

  以上幾步操作是在一個(gè)事務(wù)中完成,保證了流水號的連續(xù)。這個(gè)思路是正確的,使用起來好像也沒有什么問題,但是在業(yè)務(wù)量比較大的情況下卻經(jīng)常報(bào)錯(cuò):“訂單號違反主鍵約束,不能將重復(fù)的訂單號插入到訂單表中?!边@是怎么回事?讓我們做一個(gè)簡單的Demo來重現(xiàn)一下:

  1.創(chuàng)建種子表和訂單表,這里只是一個(gè)簡單的Demo,所以就省去了很多字段,而且訂單號假設(shè)就是一個(gè)流水號,不用再使用年月日+6位流水號了。

CREATETABLESeek--種子表
(
  SeekValueINT
)
GO
INSERTINTOSeekVALUES(0)--種子初始值為0
GO
CREATETABLEOrders
(
  OrderIDINTPRIMARYKEY,--訂單號,主鍵
  RemarkVARCHAR(5)NOTNULL
)

  2.創(chuàng)建一個(gè)存儲(chǔ)過程,該存儲(chǔ)過程傳入Remark參數(shù),根據(jù)生成的流水號插入到訂單表中:

  CREATEPROCAddOrder--Author:深藍(lán)

  @remarkVARCHAR(5)--傳入的參數(shù)

  AS

  DECLARE@seekint

  BEGINTRAN --開啟一個(gè)事務(wù)

  SELECT@seek=SeekValue--讀取種子表中的最大值作為流水號

  FROMSeek

  --生成訂單號這一步省略,因?yàn)檫@里假定的訂單的編號就是流水號

  UPDATESeekSETSeekValue=@seek+1--更新種子表,使最大值+1

  INSERTINTOt1VALUES(@seek,@remark)--插入一條訂單數(shù)據(jù)

  COMMIT--提交事務(wù)

  3.新建一個(gè)查詢窗口,使用以下語句調(diào)用創(chuàng)建的存儲(chǔ)過程,不斷的插入新訂單:

  WHILE1=1

  EXECAddOrder'test1'--不斷的插入訂單

  4.再新建一個(gè)查詢窗口,使用通過的方式,不斷的插入新訂單,這樣用于模擬高并發(fā)時(shí)候的情況:

WHILE1=1
EXECAddOrder'test2'

  5.運(yùn)行了一段時(shí)間后,我們停止這兩個(gè)死循環(huán),我們可以看到消息窗口中存在大量的異常:

  消息 2627,級別 14,狀態(tài) 1,過程 AddOrder,第 11 行

  違反了 PRIMARY KEY 約束 'PK__Orders__C3905BAF08EA5793'。不能在對象 'dbo.Orders' 中插入重復(fù)鍵。

  語句已終止。

  為什么會(huì)這樣呢?這得從事務(wù)隔離級別和鎖來解釋:

  一般我們寫程序時(shí)都是使用的是默認(rèn)的事務(wù)隔離級別——已提交讀,在第一步查詢Seek表時(shí),系統(tǒng)會(huì)為該表放置共享鎖,而鎖的兼容性中共享鎖和共享鎖是可以兼容的,所以一個(gè)事務(wù)在讀取Seek表最大值時(shí),其他事務(wù)也可以讀取出相同的最大值,兩個(gè)事務(wù)中讀取到了相同的最大值,所以產(chǎn)生了相同的流水號,所以產(chǎn)生了相同的訂單號,所以才會(huì)出現(xiàn)違反主鍵約束的錯(cuò)誤。

  既然知道了這其中的原理了,那么解決辦法也就有了,只需要先對種子表中的數(shù)+1,然后再進(jìn)行讀取即可,修改存儲(chǔ)過程如下:

ALTERPROCAddOrder--Author:深藍(lán)
@remarkVARCHAR(5)
AS
DECLARE@seekint
BEGINTRAN
UPDATESeekSETSeekValue=SeekValue+1 --先修改數(shù)據(jù)
SELECT@seek=SeekValue-1--已經(jīng)加了1,所以這里-1下來
FROMSeek
INSERTINTOOrdersVALUES(@seek,@remark)
COMMIT

  為什么這樣寫就可以呢?第一步執(zhí)行更新操作,系統(tǒng)會(huì)請求更新鎖然后再升級為排他鎖,因?yàn)楦骆i和更新鎖以及排他鎖都是不兼容的,所以一個(gè)事務(wù)對Seek表進(jìn)行了更新后,其他的事務(wù)就不能對表進(jìn)行更新操作,只有等到事務(wù)提交以后才能繼續(xù)。

  這里附上鎖兼容性表:

現(xiàn)有授予模式
請求模式 IS S U IX SIX X
意向共享 (IS)
共享 (S)
更新 (U)
意向排他 (IX)
意向排他共享 (SIX)
排他 (X)


該文章在 2011/3/3 17:38:45 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲(chǔ)管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

主站蜘蛛池模板: 中文字幕无码精品亚洲资源网 | A欧美爰片久久毛片A片 | 一本一道av无码中文字幕﹣百度 | 高潮毛片无遮挡高清免费 | 呦男呦女精品视频十区 | 国产真实孩交 | 国产色精品久久人妻无码看片软件一区一个亚洲 | 2025国产91精品久久久久久 | 人妻少妇久久中文字 | 国产女同调教 | 91精品国产欧美一区二区 | 高清偷自拍第1页 | 五月天堂婷婷爱五月丁香天堂网 | 国产真实强被迫伦姧女在线观看 | 欧美日韩国产小电影 | 精品人妻av无码一区二区三区 | 中文成人av人妻区 | 亚洲精品乱码久久久久久蜜桃不 | 欧美专区亚洲电影在线观看 | 国产精品免费一区二区三区四区 | 欧美日韩国产免费一区二区三区蜜桃亚洲国产一区二区三 | 国产女人久久精品 | 精品人妻视频 | 国产成人欧美一区二区三区在线 | 亚洲av无码国产一区二区 | 亚洲又黄又大又爽毛片 | 亚洲成av人熟女午夜免费电影 | 久久国产伦子伦精品 | 国产精品人妻一区二区三区四(免费)在线观看 | 日韩午夜理论免费tv影院 | 欧美日韩国产另类激情图区 | 91精品人妻aⅴ区 | 国产网爆门视频在线播放 | 无码人妻品一区二区三区精99 | 中文字幕一区波多野结衣 | 欧美精品狠狠色丁香婷婷 | 久久精品亚洲乱码伦伦中文 | 伊人一区二区三区四区 | 国语自产拍在线观看偷拍在 | 国产日韩亚洲欧美区 | 国产精品自在拍一区二区不卡 |