2010-08-12 46 views
2

我有2個表。以下只是這些表格的簡化版本。如何解決這個存儲過程問題

TableA 
Id <pk> incrementing 
Name varchar(50) 

TableB 
TableAId <pk> non incrementing 
Name varchar(50) 

現在這些表格之間有相互關係。

方案

用戶1來到我的網站,做一些動作(在這種情況下添加行表A)。所以我在表A中使用SqlBulkCopy所有這些數據。

但是我需要將數據也添加到表B,但我不知道表A中新創建的Id,因爲SQLBulkCopy不會返回這些數據。

所以我想具有查找所有ID的不表B中存在,然後將其插入存儲過程。

INSERT INTO TableB (TableAId , Name) 
SELECT Id,Name FROM TableA as tableA 
WHERE not exists(...) 

但是這個帶有一個問題。用戶在任何時候都可以從TableB中刪除某些東西,所以如果用戶刪除了一行說,然後另一個用戶來了,甚至相同的用戶來了,並做了表A的一些事情,我的存儲過程將帶回表B中刪除的行。由於它仍然存在於表A中而不是表B中,因此滿足存儲過程條件。

那麼有沒有更好的方式來處理使用批量插入時需要更新的兩個表?

+1

我非常確定RDMS的整個目標是避免在有多個併發連接時互相排斥和更新問題。我不是數據庫專家,也不是在電視上播放,但據我所知,有些結構可以用來使查詢成爲「原子」。 – 2010-08-12 19:17:13

+0

@San Jacinto:正確,但SQLBulkCopy是一個複雜的問題。即使這樣,以後的寫入也無法區分哪些行是他們的,哪些是來自先前寫入的,並與B中的間隙有關。 – gbn 2010-08-12 19:41:07

回答

3

SqlBulkCopy的複雜這個所以我考慮使用一個臨時表和OUTPUT clause

實施例,在客戶端的僞代碼SQL

create SQLConnection 

Create #temptable 
Bulkcopy to #temptable 

Call proc on same SQLConnection 

proc: 
    INSERT tableA (..) 
    OUTPUT INSERTED.key, .. INTO TableB 
    SELECT .. FROM #temptable 

close connection 

註釋的混合物:

  • 可接受本地連接並被隔離

  • 對A和B的寫入將是原子的
  • 重疊或稍後寫入不關心稍後對A和B發生什麼
  • 強調最後一點,A和B將只填充#temptable

備選:

添加另一列A和B稱爲會話ID,並用它來確定行批處理。

1

一種選擇是使用SQL服務器的輸出條款:

INSERT YourTable (name) 
OUTPUT INSERTED.* 
VALUES ('NewName') 

這將插入的行id, name返回給客戶端,這樣你就可以在插入操作使用他們的第二個表。

+0

這就是爲什麼我說SQLBulkCOpy使這變得複雜:沒有OUTPUT子句... – gbn 2010-08-12 19:26:18

1

正如替代解決方案一樣,您可以使用database triggers更新第二個表。

+0

簡單,但您需要指定[火災觸發器] [http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopyoptions.aspx]可能需要DDL權限 – gbn 2010-08-12 20:01:39