2012-06-20 20 views
1

這更多的建議請求比問題。2存儲過程或使用合併語句

要從c#中插入/更新SQL服務器中的記錄,你會寫2個存儲過程。其中用於插入使用,將根據傳入的(這將是null或ID插入或更新記錄SQL合併陳述的紀錄,另一個用於更新記錄

寫1存儲過程0,如果它是新記錄)?

什麼是最好的標準?

我正在使用SQL Server 2008和C#4.0。

在此先感謝

+0

當你說「從C#」你的意思是ADO.NET或SQL CLR程序集? –

+0

它使用ADO.Net – Sun

+0

我喜歡他們提供的小工作單元。這樣,不同的技術可以毫不含糊地恰當地使用它們。 – Josh

回答

5

這是一個相當廣泛的問題,但根據您的業務邏輯肯定有一些可以說。

不是專注於存儲過程的內部,而是想想像這樣的問題:我是否希望存儲過程爲插入/更新指定邏輯,還是我希望應用程序能夠?

讓我們舉一個使用用戶數據的例子。用戶登錄到網站,並且您需要保存一些關於它們的信息。用戶保證有一個唯一的電子郵件地址,因爲這是您設置應用程序端業務邏輯的方式。

您可以將電子郵件地址以及其他用戶信息傳遞到存儲過程。然後,SP可以決定如何保存它。如果電子郵件不在表格中,它將執行插入操作。如果是,它會進行更新。這可以通過merge語句或if語句來完成。

更重要的是如何這樣做,是確保你將數據庫ID保留在數據庫中。做不是把它們帶到應用層,除非絕對需要。數據庫ID是表格相互引用而不重複數據字段的一種方式。 (谷歌的「一般形式」的一些信息。)他們應該絕對沒有必要在你的應用層。

無論您使用何種數據,您都應該能夠找到一個唯一的屬性或一組屬性,它們將允許您構建一個可以處理插入或更新的單個存儲過程。

P.S.我目前遇到了問題來了,在其中,你會想要兩個存儲的特效場景,但如果我可以,我會更新這個答案...

UPDATE

假設我們已經有了列出用戶,其中用戶如下。

class User 
    int id; 
    string name; 
    string email; 

您從某處獲得姓名和電子郵件,但您沒有ID。將用戶插入用戶列表時,增加一些整數並將新用戶的ID分配給該號碼。然後,將該數字傳遞到將執行合併或插入/更新的存儲過程中。這樣,你永遠不會傳入一個空的id到存儲過程中。

爲了不使數據庫透視更容易混淆,請命名保存此值「application_id」的列。 如果您需要在數據庫表中有一個單獨的自動遞增的ID,您也可以添加該ID。

+0

感謝您的建議。如果你不介意諾拉,另一個快速的問題。我檢查是否存在記錄將通過我將傳入SP的ID值。你會通過null還是0?並且在SP中你會聲明一個默認值爲null或0的參數?謝謝 – Sun

+0

總得問:是否可以使用其他值,而不是ID? –

+0

不是。我沒有別的方法來識別沒有ID的記錄。 – Sun

3

當我發送 收集數據(數據表),這可能 包含新數據或更新現有的數值數據的,我會用合併。 否則對於單個插入和更新我會 使用單獨的存儲過程。對於單個插入和更新 ,您還可以使用單個存儲過程 - 如果主鍵值 不存在 - 請創建該記錄。如果存在 - 更新記錄。

+1

更好的方法(避免查找)是更新行,如果rowcount爲0,則插入。 –

+0

@AaronBertrand對於如何避免查找/掃描,我有點困惑。 UPDATE語句不一定要掃描表或索引來嘗試操作嗎? –

+2

是的,但如果你首先說'IF EXISTS(SELECT * FROM table WHERE key = @key)',然後說'(UPDATE table SET val = @val WHERE key = @key)',你做了兩個操作,而不是一個(只有後者是必要的;結果告訴你前者會告訴你的同樣的事情)。如果它最終成爲一個插入,無論你做了兩個搜索。我應該說「*潛在*避免尋求」 - 這一切都取決於更新與插入的比率,它有多好。 –

1

有趣的問題!我們只是在解決這個問題。

我們只是圍繞MERGE發現我們的頭腦,並發現它最適合SETS記錄之間的更新/插入/刪除協調。讓它爲單個記錄工作是非常複雜的。

所以,我們去了單獨的INSERT和UPDATE路由,但是我們把兩者放在同一個'upsert'存儲過程中。

+1

我想禮貌地推薦嘗試使用MERGE,如果可能的話。合併而不是插入,允許您在單個事務中執行整個操作,從而幫助緩解可能發生的併發問題。 –

+0

大點諾拉。我們應該更多地研究它。同時,我們在事務中封裝了整個update-check-insert。 – n8wrl

+0

感謝您的建議。 – Sun