7

どこから始めればよいのか、これがどのように機能するのかわかりません。誰かがアイデアや実績のある方法を持っていることを願っています.

私がやろうとしていることの例を示すために、リンク テーブルからレコードを取得してローカル テーブルの新しいレコードを更新または挿入するストアド プロシージャを作成しました。ストアド プロシージャは、SQL Server のジョブとして実行され、新しいレコードを更新および挿入します。

私の質問は次のとおりです。最初にすべてのレコードを取得できるが、挿入された新しいレコードまたは更新された古いレコードのみを取得できるように、ローカル テーブルのデータをクエリする方法はありますか?

すべてのレコードを継続的に取得したくはありません。新しいレコードが追加されたか、レコードが更新されただけです。

これは可能ですか?

ローカル電話データを更新する例として作成したストアド プロシージャを次に示します。

CREATE PROCEDURE sp_UPDATE_PHONE_RECORDS
AS 
BEGIN
MERGE dbo.PHONE_REC AS Target
USING (SELECT MEMBER_ID 
      ,HOME_PHONE = dbo.udf_StdPhoneFmt(HOME)
      ,CELL_PHONE = dbo.udf_StdPhoneFmt(CELL)
      ,WORK_PHONE = dbo.udf_StdPhoneFmt(WORK)

FROM PHONE WHERE MEMBER_ID IS NOT NULL) AS SOURCE

ON (Target.MEMBER_ID = SOURCE.MEMBER_ID)

WHEN MATCHED THEN

    UPDATE SET Target.HOME_PHONE = Source.HOME_PHONE,Target.CELL_PHONE = Source.CELL_PHONE,
    Target.WORK_PHONE = Source.WORK_PHONE

WHEN NOT MATCHED BY TARGET THEN
    INSERT (MEMBER_ID, HOME_PHONE, CELL_PHONE ,WORK_PHONE)

    VALUES (Source.MEMBER_ID, Source.HOME_PHONE, Source.CELL_PHONE, Source.WORK_PHONE);
END
GO

これは可能ですか?

みんな、ありがとう!

4

5 に答える 5

6

通常は、Source.LastModifiedOnやSource.CreatedOnなどの2つの日付/時刻フィールドをソーステーブルに追加します。

次に、ジョブを実行してターゲットテーブルを更新するときに、ジョブが最後に実行されてからのすべてのSource.LastModifiedOn行とSource.CreatedOn行を取得し、行に基づいて更新/挿入を行うと言うことができます。

もちろん、Source.LastModifiedOnとSource.CreatedOnが正しく設定されていることを確認する必要があります。

于 2012-04-30T21:56:13.550 に答える
4

列でOUTPUT 句を使用します。$action

DECLARE @Target TABLE
(
    Id INT NOT NULL,
    Value VARCHAR(10) NULL
);
INSERT  @Target
VALUES  (1, 'A'),  (2, NULL), (3, NULL);    
DECLARE @Source TABLE
(
    Id INT NOT NULL,
    Value VARCHAR(10) NULL
);
INSERT  @Source
VALUES  (2, 'B'), (4, 'D'), (5, 'E');
DECLARE @AffectedRows TABLE
(
    MergeAction     NVARCHAR(10) NOT NULL,
    Old_Id          INT NULL,
    Old_Value       VARCHAR(10) NULL,
    New_Id          INT NULL,
    New_Value       VARCHAR(10) NULL
);

MERGE   @Target t
USING   @Source s ON t.Id = s.Id
WHEN MATCHED THEN
        UPDATE SET Value = s.Value
WHEN NOT MATCHED THEN
        INSERT (Id, Value) VALUES (s.Id, s.Value)
OUTPUT  $action, deleted.Id, deleted.Value, inserted.Id, inserted.Value 
        INTO @AffectedRows(MergeAction, Old_Id, Old_Value, New_Id, New_Value);

SELECT  * FROM  @Target;
SELECT  * FROM  @AffectedRows;

結果:

Id Value
-- -----
1  A
2  B    <-- updated row
3  NULL
4  D    <-- inserted row
5  E    <-- inserted row

MergeAction Old_Id      Old_Value  New_Id      New_Value
----------- ----------- ---------- ----------- ---------
INSERT      NULL        NULL       4           D
INSERT      NULL        NULL       5           E
UPDATE      2           NULL       2           B
于 2012-04-30T22:27:54.990 に答える
0

これは基本的にRDotLeeの回答のバリエーションですが、レコードが作成された実際の日付/時刻を気にしない場合に時々使用する代替アプローチです:

デフォルト値 1bitで呼び出される 1 つのフィールドを追加するだけです。 新しい行がテーブルに挿入されると、自動的に 1 に設定されます。 既存の行が更新された場合、それも1 に設定されていることを確認する必要があります。modified
modified
modified

そうすれば、ジョブは ですべての行を検索するだけで済みますmodified = 1
ジョブが最後に実行された日時を追跡する必要はありません。

modifiedジョブが正常に実行されると、最後にすべての行のフィールド が「リセット」されます。

update TheTable set modified = 0

IMO、このアプローチは、最後のジョブの実行以降に行が変更されたことだけを気にする場合は作業が少なくなりますが、行が変更された場合はそうではありません。

ただし、RDotLee の「LastModifiedOn/CreatedOn」アプローチと同じ欠点があります。テーブルのすべての更新が実際にmodified列を 1 に設定することを確認する必要があるため、これを使用できるのは、すべてのコードを制御している場合のみです。テーブルに書き込みます。

于 2012-05-01T10:30:42.233 に答える
0

タイムスタンプ

TimeStamp は、挿入または更新時にインクリメントされます。

マスターではタイムスタンプに、スレーブではバイナリにします(8)

select [timeStampSlave].* 
from [timeStampSlave] 
join [timeStampMaster] 
on [timeStampSlave].[ID] = [timeStampMaster].ID 
and [timeStampSlave].[timeStamp] < [timeStampMaster].[timestamp]

サーバー間でクエリを実行するには、次の構文を使用できます

[MasterSever].[test].[dbo].[timeStampMaster]
于 2012-05-01T15:58:28.033 に答える
0

更新または挿入が行われたときに起動するトリガーをローカルテーブルに書き込むことができます。トリガー ロジックの一部として、更新されたレコードまたは新しく挿入されたレコードを一時テーブルに挿入する必要があります。これは、ローカル テーブルへの変更を記録する最も簡単な方法です。

于 2012-05-01T09:41:42.740 に答える