2013-04-11 40 views
-1

使用SQL Server 2008,有三個表,表a,表b和表c。TSQL:獲取下一個可用ID

所有具有ID列,但對錶a和b的ID列是identity integer,對於表C ID列是varchar

目前存儲過程採取的名稱PARAM,以下某些邏輯,插入到表格a或表格b中,獲得標識,以'A'或'B'作爲前綴,然後插入到表格c中。

問題是,表C ID列可能具有重複值,即如果來自表A的標識爲2,表C的ID列中可能已經有'A2','A3','A5'編寫T-SQL查詢以確定表C中的下一個可用值,然後確保相應地更新表A/B?

[更新] 這是當前步驟, 1.取決於輸入參數,插入到表A或表B中 2.初始化種子值= @@身份 3.計算ID值插入到表C中通過前綴'A'或將種子值追加'B' 4.通過步驟3的ID值查找表C中的記錄匹配,如果未找到任何記錄,則插入它,否則將種子值增加1,然後重複步驟3

問題出現在某個值範圍內,表C ID中可能存在一個巨大的值塊,即現在在表C ID中存在A3000到A500000,如果遵循現有的數據庫,數據庫查詢會非常慢邏輯。需要找出一個邏輯巧妙地獲得最小可用數量(沒有前綴)

這很難描述,希望這更有意義,我真的很感謝任何幫助提前在此謝謝!

+5

重新設計這將會好得多。這真的不是一個好方法 – RBarryYoung 2013-04-11 20:33:28

+1

如果表A和B中的「ID」確實是「INT IDENTITY」 - 它怎麼會給你重複?如果你在表C中使用表前綴(A或B)加上表A或B中'ID'列的** unique **值,那麼對我來說這似乎是不可能的。 – 2013-04-11 20:35:27

+0

@Tommy Wang,你能編輯你的文章並給我們一個更詳細的例子嗎? – PowerUser 2013-04-11 21:00:10

回答

1

這應該是關鍵。簡單的自我提取示例將在SSMS中運行。爲了以防萬一,我甚至做到了這一點。您只需將您的表更改爲@Data所在的位置,然後更改標識符字段以替換「ID」。

declare @Data Table (Id varchar(3)); 

insert into @Data values ('A5'),('A2'),('B1'),('A3'),('B2'),('A4'),('A1'),('A6'); 

With a as 
    (
    Select 
     ID 
    , cast(right(Id, len(Id)-1) as int) as Pos 
    , left(Id, 1) as TableFrom 
    from @Data 
    ) 
select 
    TableFrom 
, max(Pos) + 1 as NextNumberUp 
from a 
group by TableFrom 

編輯:如果你想不用擔心生產數據,你可以添加最後一部分修改我寫的:

Select 
    TableFrom 
, max(Pos) as LastPos 
into #Temp 
from a 
group by TableFrom 

select TableFrom, LastPos + 1 
from #Temp 

不管,如果這是生產環境下,你將不得不打的一部分它在某個時間獲取數據。如果數據集不是太大,只是varchar(256)或更少,只有500萬行或更少,則可以將整個列從tableC轉儲到臨時表。誠實地查詢性能與進口數據在系統之間變化很大。

+1

這可能在單用戶測試環境中工作得很好 - 但在負載下的生產系統中,有多個用戶正在訪問數據庫,「SELECT MAX(+ 1)」方法遲早會失敗併產生重複值。 ..... – 2013-04-11 21:28:40

+0

不夠公平,我會用臨時表格更新我的答案,以表明你的陳述可能是真實的。 – djangojazz 2013-04-11 21:59:18

+1

+1對於一個醜陋問題的良好答案。但是你只是讓一個糟糕的數據設計繼續存在。 – Paparazzi 2013-04-11 22:17:48

1

按照您的設計,考慮到A和B是唯一的,表C中不應有任何重複項。

A | B | C 
1 1 A1 
2 2 A2 
     B1 
     B2