基于复合主键值读取增量数据

r6vfmomb  于 2021-06-20  发布在  Mysql
关注(0)|答案(2)|浏览(401)

我有一个oltp(源),数据必须从这里以增量的方式移动到dwh(目标)。源表在loan\u id assetid上有一个复合主键,如下所示。

LOAN_ID, ASSETID, REC_STATUS
'12848','13170', 'F'

如果它是一个单列主键,那么我将检查目标列的最大值,然后从主键值大于目标列最大值的源中读取所有记录,但由于它是一个复合主键,因此这将不起作用。
您知道如何使用t-sql查询来实现这一点吗?
规范:源是一个mysql数据库,目标是mssql2012。使用链接服务器建立连接。

y0u0uwnf

y0u0uwnf1#

增量负载通常有一个驱动它们的日期。
可以在查找中使用复合键。这个问题已经回答了很多次了。
添加查找并将测试更改为重定向no match(默认为fail)。
基本上,您检查目的地中是否存在密钥。
如果密钥存在,则它是一个更新(匹配)。
如果密钥不存在(不匹配),则它是一个insert。

a2mppw5e

a2mppw5e2#

有几件事你可以试试。处理链接服务器时,不知道该设置的细节以及数据量,性能可能是一个问题。
如果您不担心现有记录的更改或删除,那么简单的左-外连接将获得尚未插入到目标中的所有记录:

SELECT          [s].[LOAD_ID]
              , [s].[ASSETID]
              , [s].[REC_STATUS]
FROM            [LinkedServer].[Database].[schema].[SourceTable] [s]
LEFT OUTER JOIN [DestinationTable] [d]
    ON [s].[LOAN_ID] = [d].[LOAN_ID]
       AND [s].[ASSETID] = [d].[ASSETID]
WHERE           [d].[LOAN_ID] IS NULL;

如果您担心更改,您仍然可以使用left outer并查找目标中的null或字段值中的差异,但是您需要一个额外的update语句。

SELECT          [s].[LOAD_ID]
              , [s].[ASSETID]
              , [s].[REC_STATUS]
FROM            [LinkedServer].[Database].[schema].[SourceTable] [s]
LEFT OUTER JOIN [DestinationTable] [d]
    ON [s].[LOAN_ID] = [d].[LOAN_ID]
       AND [s].[ASSETID] = [d].[ASSETID]
WHERE           [d].[LOAN_ID] IS NULL --Records from source not in destination
                OR (
                        --This evaluates those in the destination, but then checks for changes in field values.
                       [d].[LOAN_ID] IS NOT NULL
                       AND (
                               [s].[REC_STATUS] <> [d].[REC_STATUS]
                               OR [s].[SomOtherField] <> [d].[SomeOtherField]
                           )
                   );

--The above insert into some landing or staging table on the destination side and then you could do a MERGE.

如果我们需要担心删除。记录已从源中删除,您不希望它再出现在目标中。翻转左外侧以查找目标中不再位于源中的记录:

DELETE [d]
FROM           [DestinationTable] [d]
LEFT OUTER JOIN [LinkedServer].[Database].[schema].[SourceTable] [s]
    ON [s].[LOAN_ID] = [d].[LOAN_ID]
   AND [s].[ASSETID] = [d].[ASSETID]
WHERE           [s].[LOAD_ID] IS NULL;

您可以尝试使用合并来执行所有这些操作。尝试通过链接服务器进行合并,或者将所有源记录放到land/stage表中的目标位置,然后在那里进行合并。下面是一个通过链接服务器进行尝试的示例。

MERGE [DestinationTable] [t]
USING [LinkedServer].[Database].[schema].[SourceTable] [s]
ON [s].[LOAN_ID] = [d].[LOAN_ID]
   AND [s].[ASSETID] = [d].[ASSETID]
WHEN MATCHED THEN UPDATE SET [REC_STATUS] = [s].[REC_STATUS]
WHEN NOT MATCHED BY TARGET THEN INSERT (
                                           [REC_STATUS]
                                       )
                                VALUES ( [s].[REC_STATUS] )
WHEN NOT MATCHED BY SOURCE THEN DELETE;

处理合并时,请注意以下语句:

WHEN NOT MATCHED BY SOURCE THEN DELETE;

如果不使用整个记录集,则可能会丢失目标中的记录。例如,您已经将从源中提取的结果集限制到暂存表中,现在将暂存表与最终目标合并,超出此范围的任何内容都将在目标中删除。你可以通过限制你的目标与cte,谷歌:“合并到cte作为目标”。如果你有可以筛选的日期。
如果您有一个日期列,这总是很有帮助的,特别是在插入或更新新记录时,某些类型的更改/更新日期列。然后你可以在你的源代码中过滤到你所关心的那些记录。

相关问题