Using Change Tracking
A worked example of polling CHANGETABLE(CHANGES) with an anchor version to pull incremental changes.
The core change tracking pattern. You hold an anchor version - the point in change history you have already consumed - and each poll queries CHANGETABLE(CHANGES table, @AnchorVersion), which returns every row changed since that anchor along with the operation (I/ins, U/upd, D/del) and version numbers. Join back to the base table on the primary key to get current values, filter to versions at or below CHANGE_TRACKING_CURRENT_VERSION() so you only see committed changes, then advance your anchor. The second query shows the same poll twenty minutes later against a different table using the original anchor.
DECLARE @AnchorVersion BigInt
DECLARE @CurrentVersion BigInt
SET @AnchorVersion = 10
SET @CurrentVersion = CHANGE_TRACKING_CURRENT_VERSION()
SELECT @AnchorVersion as AnchorVersion, @CurrentVersion as CurrentVersion
SELECT
Tracking.SYS_CHANGE_OPERATION,
Tracking.SYS_CHANGE_VERSION,
Tracking.SYS_CHANGE_CREATION_VERSION,
Tracking.<PK Column(s)>,
Base.*
FROM
CHANGETABLE(CHANGES dbo.<Table Name>, @AnchorVersion) AS Tracking
LEFT OUTER JOIN dbo.<Table Name> AS Base (NOLOCK)
ON Base.<PK Column(s)> = Tracking.<PK Column(s)>
WHERE
Tracking.SYS_CHANGE_VERSION <= @CurrentVersion
--20 minutes passes--
SELECT
Tracking.SYS_CHANGE_OPERATION,
Tracking.SYS_CHANGE_VERSION,
Tracking.SYS_CHANGE_CREATION_VERSION,
Tracking.<PK Column(s)>,
Base.*
FROM
CHANGETABLE(CHANGES dbo.<Some Other Table Name>, @AnchorVersion) AS Tracking
LEFT OUTER JOIN dbo.<Some Other Table Name> AS Base (NOLOCK)
ON Base.<PK Column(s)> = Tracking.<PK Column(s)>
WHERE
Tracking.SYS_CHANGE_VERSION <= @CurrentVersion