2009-04-12 73 views
10

所以我有一箇舊的數據庫,我正在遷移到一個新的。新的有一個略有不同,但大多數兼容的模式。另外,我想重新編號從零開始的所有表格。TSQL:更新與插入選擇從

目前我一直在使用我寫的手動檢索舊記錄的工具,將它插入到新數據庫中,並更新舊數據庫中的v2 ID字段以在新數據庫中顯示其相應的ID位置。

例如,我從MV5.Posts中選擇並插入到MV6.Posts中。插入後,我檢索MV6.Posts中新行的ID,並在舊MV5.Posts.MV6ID字段中更新它。

有沒有辦法做到這一點更新通過INSERT INTO SELECT FROM,所以我不必手動處理每個記錄?我正在使用SQL Server 2005,開發版。

回答

9

與遷移的關鍵是做幾件事情:一是 ,沒有做任何事情沒有最新的備份。 其次,如果密鑰將會改變,您需要至少暫時在新結構中存儲舊的和新的(永久性地如果密鑰字段暴露給用戶,因爲它們可能正在搜索它以獲取舊記錄)。

接下來,您需要深入瞭解與子表的關係。如果您更改關鍵字段,則所有相關表格也必須更改。這是存儲新舊密鑰的地方。如果您忘記更改其中的任何一項,數據將不再正確,並且將無用。所以這是關鍵的一步。

挑出一些特別複雜數據的測試用例,確保爲每個相關表格包含一個或多個測試用例。將現有值存儲在工作表中。

要開始遷移,請使用舊錶中的選擇插入到新表中。根據記錄數量的不同,您可能希望循環執行批處理(一次不記錄一條記錄)以提高性能。如果新密鑰是標識,只需將舊密鑰的值放入其字段中,並讓數據庫創建新密鑰。

然後對相關表格做同樣的處理。然後,使用舊的鍵值在表中的東西,如更新外鍵字段:

Update t2 
set fkfield = newkey 
from table2 t2 
join table1 t1 on t1.oldkey = t2.fkfield 

測試您的遷移與您在遷移前存儲什麼運行測試用例和比較數據。徹底測試遷移數據或者無法確定數據是否與舊結構一致是非常關鍵的。移民是一項非常複雜的行動;花費你的時間並且非常有條理和徹底地完成它是值得的。

0

AFAIK,你不能更新一個SQL語句

但是,您可以使用觸發器來實現你想做的事兩個不同的表。

2

我知道的最好的辦法是與output clause。假設你有SQL 2005或2008.

USE AdventureWorks; 
GO 
DECLARE @MyTableVar table(ScrapReasonID smallint, 
          Name varchar(50), 
          ModifiedDate datetime); 
INSERT Production.ScrapReason 
    OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate 
     INTO @MyTableVar 
VALUES (N'Operator error', GETDATE()); 

它仍然需要第二遍更新原始表;不過,它可能會使你的邏輯更簡單。你需要更新源表嗎?您可以將新的ID存儲在第三個交叉引用表中。

1

heh。我記得在遷移中這樣做。

將old_id放入新表中使得更新變得更容易 - 您可以僅執行一次insert into newtable select ... from oldtable,以及後續的「拼接」記錄。在「針」中,您將通過在新父項(insert into newchild select ... (select id from new_parent where old_id = oldchild.fk) as fk, ... from oldchild)上執行子選擇來更新子插入表中的子表的外鍵,否則您將插入子項並執行單獨更新以修復外鍵。

在一個插入中做它會更快;在單獨的步驟中進行測量,以確定您的插入不依賴於順序,並且可以在必要時重新進行。

遷移後,您可以刪除old_id列,或者,如果您有遺留系統公開系統ID並且用戶使用這些密鑰作爲數據的情況,則可以保留它們以允許使用基於old_id。

事實上,如果您正確定義了外鍵,則可以使用systables/information-schema來生成插入語句。

4

可能最簡單的方法是在MVI上爲oldId添加一列,然後將舊錶中的所有記錄插入到新表中。

UPDATE mv5.posts 
SET newid = n.id 
FROM mv5.posts o, mv6.posts n 
WHERE o.id = n.oldid 

你可以清理,之後刪除OLDID列,如果你想:最後,用類似更新在新表上OLDID舊錶匹配。

+0

我實際上認爲把oldId留在新表上比在舊錶上使用newId更好,這使得它更容易。 – ninesided 2009-04-13 01:11:04

0

在MV6.Post.OldMV5Id

做出 INSERT INTO MV6.Post 選擇使列..從MV5.Post

然後作出MV5.Post的更新。MV6ID

1

有沒有辦法通過INSERT INTO SELECT做到這一點的更新不這樣我就不必手動處理每一條記錄?

既然你不想做手動,但自動,在MV6.Posts創建一個觸發器,這樣,當你插入MV6.Posts發生UPDATEMV5.Posts自動。

而且你的觸發可能看起來像,

create trigger trg_MV6Posts 
on MV6.Posts 
after insert 
as 
begin 
    set identity_insert MV5.Posts on 

    update MV5.Posts 
    set ID = I.ID 
    from inserted I 

    set identity_insert MV5.Posts off 
end