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同じ定義ですが、さらに多くのデータ行が含まれます。必要なのは、見たことのない値をから挿入TableATableMain、既存の行を更新することです。

私はこの種の挿入を行っていましたが、更新と複合主キーの処理方法がわかりません:

INSERT INTO TableMain 
    SELECT * FROM TableA

編集:私はSQL Server 9.00.5000を使用しています

EDIT:MERGEに触発され、それを模倣する別の方法

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

3 に答える 3

5

マージステートメントを使用する必要があります

このようなもの:

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>
于 2012-08-09T12:41:57.480 に答える
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パフォーマンスが不十分であるかのように not exists() を書き直すかもしれません。

于 2012-08-09T13:16:36.723 に答える
3

SQLServer 2008 のMergeコマンドを使用できます。これにより、別のデータ ソースからメイン データ ソースにデータをマージし、キーが一致したとき (おそらくテーブルを更新したいとき) に特定の動作を定義できます。一致しないため、新しいレコードを挿入したいと思うでしょう。

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

このリンクにアクセスして、いくつかのコード サンプルを取得できます。

于 2012-08-09T12:17:52.003 に答える