Sql 如何创建只获取表中已更新数据的查询

Sql 如何创建只获取表中已更新数据的查询,sql,sql-server,sql-server-2008,tsql,Sql,Sql Server,Sql Server 2008,Tsql,我不知道从哪里开始,也不知道这将如何运作,我希望有人有一个想法或一个行之有效的方法 为了演示我正在尝试执行的操作,我创建了一个存储过程,通过从链接表获取记录来更新或插入本地表中的新记录。存储过程在SQL Server中作为作业运行,以更新和插入新记录 我的问题是:是否有一种方法可以查询本地表中的数据,以便最初可以获取所有记录,而不是仅获取已插入的新记录或已更新的旧记录 我不想连续获取所有记录,只想添加新记录或更新记录 这可能吗 以下是我创建的用于更新本地电话数据的存储过程: CREATE PRO

我不知道从哪里开始,也不知道这将如何运作,我希望有人有一个想法或一个行之有效的方法

为了演示我正在尝试执行的操作,我创建了一个存储过程,通过从链接表获取记录来更新或插入本地表中的新记录。存储过程在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
这可能吗


谢谢大家

我们通常会在源表中添加两个日期/时间字段,如source.LastModifiedOn和source.CreatedOn

然后,当作业运行以更新目标表时,您可以说get me all Source.LastModifiedOn和Source.CreatedOn行(自上次作业运行以来),并基于这些行执行更新/插入

当然,您需要确保Source.LastModifiedOn和Source.CreatedOn设置正确。

我将与
$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
Id值
-- -----
1A

2 B您可以在本地表上写入触发器,当对其进行更新或插入时,将触发该触发器。作为触发器逻辑的一部分,您必须将更新或新插入的记录插入到临时表中。这是记录对本地表所做更改的最简单方法

这基本上是的一种变体,但当我不关心创建记录的实际日期/时间时,我有时会使用另一种方法:

我只需添加一个名为
modified
bit
字段,默认值为1。
如果在表中插入新行,
modified
将自动设置为1。
如果更新现有行,我必须确保
modified
也设置为1

这样,作业只需搜索
modified=1
的所有行
无需跟踪上次执行作业的日期/时间

当作业成功执行时,它所做的最后一件事是“重置”所有行中的
modified
字段:

update TheTable set modified = 0
在我看来,如果只关心自上次作业运行以来对行进行了修改,而不关心对行进行了修改,那么这种方法的工作量就会减少

但它与RDotLee的“LastModifiedOn/CreatedOn”方法具有相同的缺点-您需要确保表上的每次更新都将
modified
列设置为1,因此您只能在控制写入表的所有代码时使用它。

时间戳

时间戳在和插入或更新时递增

在主机上使其成为时间戳,在从机上使其成为二进制(8)


我觉得这是一个合适的工具。我将使用你的例子并反馈反馈,不想将其标记为答案,以防我有其他问题。但感谢您花时间回答。:)@如果你有问题,请随时提问。如果我知道答案,我会帮助你。这是一个有趣的方法。:)再次感谢!好吧,我找到了一个有效的解决方案,不确定它是否是最好的,它是这里发布的想法的组合。我所做的是在本地表上创建一个时间戳列。这会在每次更新记录或插入新记录时向记录(行)添加SMALLDATETIME。现在,我可以根据在过去24小时内更新或插入的记录,或者使用时间戳查询本地表。我怎样才能把代码发回到这里?@unserageguy你是说时间戳吗?这不是一个很短的时间。我在3小时前发布了答案。不,我在本地表上创建了一列,并将该列命名为TIME_STAMP,数据类型为smalldatetime。我现在需要知道的是,如何使用TIME\u STAMP列中的datetime查询本地表,以获得在此时间和该时间之间插入或更新的所有记录。这与我发布的查询类似。但您应该真正了解时间戳,因为它在插入和更新时自动递增。SmallDateTime只适用于分钟,因此如果同步,那么在同一分钟内更新,则不会重新同步。我非常感谢您的帮助。在您看来,使用实际日期对我来说比使用时间戳更好,因为该表将从链接表每天更新一到两次。我现在需要做的就是创建一个查询,该查询显示:从本地表中获取所有日期,该表是在这个时间和那个时间之间创建的,或者是在昨天和今天之间创建的。
select [timeStampSlave].* 
from [timeStampSlave] 
join [timeStampMaster] 
on [timeStampSlave].[ID] = [timeStampMaster].ID 
and [timeStampSlave].[timeStamp] < [timeStampMaster].[timestamp]
[MasterSever].[test].[dbo].[timeStampMaster]