我不知道从哪里开始或者这将如何运作,我希望有人有一个想法或一个经过验证的方法。
为了展示我想要做的事情的一个例子,我创建了一个存储过程,它通过从链接表中获取记录来更新或插入Local表中的新记录。存储过程在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
这可能吗?
谢谢大家!
答案 0 :(得分:6)
我们通常做的是在源表中添加两个日期/时间字段,例如Source.LastModifiedOn和Source.CreatedOn。
然后当作业运行以更新目标表时,您可以说自上次作业运行以来获取所有Source.LastModifiedOn和Source.CreatedOn行,并根据行执行更新/插入。
当然,您需要确保正确设置Source.LastModifiedOn和Source.CreatedOn。
答案 1 :(得分:4)
我会将OUTPUT clause与$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
答案 2 :(得分:0)
您可以在本地表上编写一个触发器,该触发器在对其进行更新或插入时将触发。作为触发器逻辑的一部分,您必须将这些更新或新插入的记录插入临时表中。这是您可以记录对本地表的更改的最简单方法。
答案 3 :(得分:0)
这基本上是RDotLee's answer的变体,但是当我不关心创建记录的实际日期/时间时,它是我有时使用的另一种方法:
我只需添加一个名为bit
的{{1}}字段,默认值为1
如果在表格中插入新行,modified
会自动设置为1
如果现有行已更新,我必须确保modified
也设置为1。
这样,作业只需要搜索modified
的所有行
无需跟踪上次执行作业的日期/时间。
当作业成功执行时,它最后做的是“重置”所有行中的modified = 1
字段:
modified
国际海事组织,如果您只关心 自上次作业以来修改了行,那么这种方法就不那么有效了,但 时修改了。
但它与RDotLee的“LastModifiedOn / CreatedOn”方法具有相同的缺点 - 您需要确保表上的每个更新确实将update TheTable set modified = 0
列设置为1,因此您只能在您可以控制写入表的所有代码。
答案 4 :(得分:0)
TimeStamp
TimeStamp会增加并插入或更新。
在Master上使它成为TimeStamp并在Slave上使它成为二进制(8)
select [timeStampSlave].*
from [timeStampSlave]
join [timeStampMaster]
on [timeStampSlave].[ID] = [timeStampMaster].ID
and [timeStampSlave].[timeStamp] < [timeStampMaster].[timestamp]
要跨服务器查询,您可以使用以下语法
[MasterSever].[test].[dbo].[timeStampMaster]