2013-12-17 106 views
0

這個問題似乎有點愚蠢,但我問,因爲我的SQL已經變得相當生疏。使用SQL更新現有記錄

我想在Microsoft SQL數據庫中做一個簡單的更新。我有一個我自己創建的數據庫表項的對象表示。

它得到了所有的數據庫表具有字段和現在我需要做的就是用新的數據,我從一個客戶端應用程序得到了更新數據庫中的原始記錄。我從客戶那裏得到每一個領域,甚至是沒有改變的領域。我需要以某種方式發出SQL語句:

  1. 查找數據庫中的現有記錄。
  2. 只更新數據中字段不同的記錄。

我甚至不確定是否可以在SQL語句中檢查它,或者只是簡單地覆蓋數據,而不管它是否與原始數據相同。

+0

出於好奇,你爲什麼不使用像NHibernate的或實體框架的ORM,因爲他們會解決這些問題給你。 – Dai

+0

@Dai因爲我有6個星期的時間來編寫一個相當龐大的數據應用程序,並且在記錄所有內容時編寫一份報告來啓動。所以我沒有考慮過。這是一個原型,所以我可以隨時切換到實體或nHibernate^_^ – OmniOwl

回答

0

所以這裏是一個方法:

 
1.) Do a equi join 
Table1 
FirstName LastName PrimaryKey 
Jay  Donner 1 
Steven Woods  2 
Bruce  Beard  3 
Table2 
Firstname LastName PrimaryKey 
Jay  Donner 1 
Steven Wood  2 
Bruce  Bears  3 

所以內連接

Select A.FirstName,A.LastName,A.PrimaryKey 
From Table1 A INNER JOIN Table2 B 
On A.FirstName = B.FirstName 
AND A.LastName = B.LastName 

現在的結果集將匹配字段 傑伊·唐納1

既然你想找到與 不匹配的字段可以使用'not in'命令使用子查詢,如下所示:

Select A.FirstName,A.LastName,A.PrimaryKey 
From Table1 A INNER JOIN Table2 B 
ON A.PrimaryKey =B.PrimaryKey 
Where A.PrimaryKey NOT IN (
    Select A.PrimaryKey 
    From Table1 A INNER JOIN Table2 B 
    On A.FirstName = B.FirstName 
    AND A.LastName = B.LastName 
) 

因此,上面的查詢指出:找到主鍵匹配並且屬性與名字和姓氏字段中的值不匹配的東西。

 
Steven Woods  2 
Bruce  Bear  3 

現在您知道需要更新的主鍵。接下來,用update語句遍歷表。光標是一塊蛋糕,但我想有人告訴你在這裏使用CTE遞歸。祝你好運......這就是我討厭SQL的原因。 這是一個使用遊標遞歸的例子...因此,我個人將使用Entity Framework的c#執行此任務,並將其作爲可執行命令與SSIS包一起包裝在我的SQL Server中。 反正!下面是迭代。

這裏的示例代碼沒有評論。

申報@fname如爲nvarchar(50)

Declare @LName as nvarchar(100) 

聲明@PrimaryKeyas詮釋

Declare PersonCursor CURSOR FAST_FORWARD FOR 


Select A.FirstName,A.LastName,A.PrimaryKey 
From Table1 A INNER JOIN Table2 B 
ON A.PrimaryKey =B.PrimaryKey 
Where A.PrimaryKey NOT IN (
    Select A.PrimaryKey 
    From Table1 A INNER JOIN Table2 B 
    On A.FirstName = B.FirstName 
    AND A.LastName = B.LastName 
) 


OPEN PersonCursor 

FETCH NEXT FROM PersonCursor 

INTO @FName, @LName, @Email 


WHILE @@FETCH_STATUS = 0 

BEGIN 

-- do row specific stuff here 



    UPDATE table2 
    SET [EmployeeIdentification]= @Fname, [email protected] 
    WHERE [email protected] 


FETCH NEXT FROM PersonCursor 

INTO @FName, @LName, @Email 

END 


CLOSE PersonCursor 

DEALLOCATE PersonCursor 
+0

對不起,如果答案不完整,但它應該給你非常好的主意。讓我知道,如果我漏了一個主要的漏洞。 – hidden

+0

你是對的,這確實給了我一個很好的主意。相當不錯的答案,我會繼續接受:) – OmniOwl

+0

如果你有SQL服務器2008或以上使用合併命令,而不是我的光標會很大,如下所示。我忘了那個。 – hidden

1

所以我猜你正在使用ADO.NET ...

當你加載你的對象,你會在對象上填充主鍵等效場。假設它是一個int標識或者不是,如果你正在創建一個新的對象,它將會是0。否則,它將是您從數據庫中加載它時得到的值。

當然,你必須確保你所做的任何綁定都具有價值。

因此,當你堅持對象到數據庫,檢查對象的主鍵值,並呼籲無論是插入或相應的更新方法。

正如戴秉國說,不過,你的里程將強烈的更好,如果你選擇一個ORM。實體框架有一點學習曲線。雖然我不是PetaPoco的粉絲,但對於非常小規模的項目來說,這是相當不錯的。

0

Finds an existing record in the Database

我把它放在一個存儲過程。

or if I simply have to just overwrite data regardless of it being the same as the original or not.

我個人使用的方法在這一切每一次更新。只要確保你沒有更新那些不屬於主鍵的列。例如:UPDATE table set firstname = @firstname, @lastname = lastname where userid = @userid。只要確保你不更新UserID

基於你的問題還沒有明確,你是否需要看實際的代碼?

+0

如果可能的話肯定。我不會乞求代碼,這是粗魯的^^。問題是我有很多的領域。 24確切地說。 – OmniOwl

0

你可以做到這一點,但它會非常長篇大論的速度非常快,如果有一個可爲空領域涉及它變得可怕。長期以來,標準方法只是覆蓋所有領域。 如果您想避免重複其他人的編輯,我建議您使用時間戳字段,並檢查單個列值在更新時未更改。

+0

這就是假設在他的特定用例中,多個用戶將同時更新相同的記錄,否則你甚至不必使用TimeStamp,對吧? – logixologist

+0

更新將由服務器管理,以便它們按順序進入。兩個客戶端不可能同時連接到數據庫。 – OmniOwl