2012-08-09 110 views
4

我正在尋找正確的語法和直接從SQL執行以下操作的方法:插入或更新(如果數據已經存在於裏面)TableMain來自TableA中包含的數據,相同的組合主鍵。從複合主鍵的另一個表插入或更新表

兩個表被定義爲:

CREATE TABLE TableA (
[TID0] [int] NOT NULL, 
[TID1] [int] NOT NULL, 
[language] [nvarchar](2) NOT NULL, 
[TID2] [nvarchar](200) NOT NULL, 
[text] [nvarchar](max) NULL, 
[updatedOn] [datetime] NOT NULL DEFAULT (getdate()) 
PRIMARY KEY (
    [TID0], 
    [TID1], 
    [language], 
    [TID2], 
) 
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] 

TableA將被定期刪除和填充。

TableMain作爲相同的定義,但將包含更多的數據行,我需要的是從TableA插入從未見過的值到TableMain,並更新已有的行。

我用來做這種插入的,但我不知道如何處理更新和複合主鍵:

INSERT INTO TableMain 
    SELECT * FROM TableA 

編輯:我使用的SQL Server 9.00.5000

編輯:另一種方式MERGE啓發和mimick it

DECLARE @updatedIDs TABLE(
    [TID0] [int], 
    [TID1] [int], 
    [language] [nvarchar](2), 
    [TID2] [nvarchar](200), 
       PRIMARY KEY ([TID0], [TID1], [language], [TID2]) -- as stated by Nikola Markovinović above, thanks 
); 

-- First update records 
update TableMain 
    set [text]  = source.[text], 
     [updatedOn] = source.[updatedOn] 
     OUTPUT 
     inserted.[TID0] 
     inserted.[TID1] 
     inserted.[language] 
     inserted.[TID2] 
     INTO @updatedIDs 
    from 
     TableMain AS main 
     , TableA AS source 
    WHERE  
    TableMain.[TID0]   = source.[TID0] 
    and TableMain.[TID1]  = source.[TID1] 
    and TableMain.[language] = source.[language] 
    and TableMain.[TID2]  = source.[TID2] 

-- And then insert 

insert into TableMain 
select * 
    from TableA AS source 
where not exists 
     ( 
     select 1 
     from @updatedIDs AS i 
     where i.[TID0]  = source.[TID0] 
     and i.[TID1]  = source.[TID1] 
     and i.[language] = source.[language] 
     and i.[TID2]  = source.[TID2] 
     ) 

回答

4

這裏是你可以用它來更新插入數據的腳本:

-- On error transaction is automatically rolled back 
set xact_abort on 

begin transaction 
-- First update records 
update TableMain 
    set [text]  = source.[text], 
     [updatedOn] = source.[updatedOn] 
    from TableMain 
inner join TableA source 
    on TableMain.[TID0]  = source.[TID0] 
    and TableMain.[TID1]  = source.[TID1] 
    and TableMain.[language] = source.[language] 
    and TableMain.[TID2]  = source.[TID2] 

-- And then insert 

insert into TableMain ([TID0], [TID1], [language], [TID2], [text], [updatedOn]) 
select [TID0], [TID1], [language], [TID2], [text], [updatedOn] 
    from TableA source 
where not exists 
     (
      select * 
      from TableMain 
      where TableMain.[TID0]  = source.[TID0] 
      and TableMain.[TID1]  = source.[TID1] 
      and TableMain.[language] = source.[language] 
      and TableMain.[TID2]  = source.[TID2] 
     ) 

commit transaction 

你可能重寫不存在( )爲left join ... where TableMain.TID0 is null如果表現不令人滿意。

+0

謝謝,順便說一句別人的答案也幫助我找到另一種使用OUTPUT條款(工作方式我也不知道:))...幾乎和你一樣的想法,把東西放在DECLARED表中看到:http://sqlserver-tips.blogspot.fr/2006/09/mimicking-merge-statement- in-sql.html 我不知道什麼是更有效的方法... – user1340802 2012-08-09 15:03:38

+0

ps:我還爲未來添加了另一種方式,如果它可以幫助其他人 – user1340802 2012-08-09 15:14:04

+0

@ user1340802輸出方式正確,速度可能更快,因爲所有未更新的源記錄都是新的,並且不必搜索可能更大的匹配項源表,但缺乏實現。表變量'@ updatedIDs'應該具有主鍵(TID0,TID1,language,TID2),否則Sql Server會假定它包含一行,因爲不會爲表變量收集統計信息。列應按選擇性順序排列 - 首先選擇性最強。這也適用於TableA。 – 2012-08-09 19:27:49

3

你可以從SQLServe使用Merge命令r。它允許您將來自其他數據源的數據合併到主數據源中,並在存在關鍵匹配時定義特定行爲(並且您可能想更新您的表),或者不匹配,您會喜歡插入新記錄。

http://blog.sqlauthority.com/2010/06/08/sql-server-merge-operations-insert-update-delete-in-single-execution/

你可以訪問此鏈接來獲得一些代碼示例。

+0

非常有趣,我不知道合併聲明BTW看起來像我的SQL Server 2005不接受它:/ – user1340802 2012-08-09 12:44:12

+0

合併聲明與SQLServer2008宣佈。如果您使用的是2005版本,​​我想您將不得不使用舊的方式來檢查是否存在並應用相關行爲。合併是非常強大的,並承諾原子性和性能以及許多其他好東西。 – Tamir 2012-08-09 12:47:44

5

你應該使用一個merge statment

是這樣的:

merge TableMain AS target 
using TableA as source 
ON <join tables here> 
WHEN MATCHED THEN <update> 
WHEN NOT MATCHED BY TARGET <Insert> 
WHEN NOT MATCHED BY SOURCE <delete> 
+0

合併是SQL 2008+ – podiluska 2012-08-09 13:07:21

+0

是的,但目前我async他沒有SQL2005標籤的問題:) – Diego 2012-08-10 08:55:39

相關問題