首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用CDC或使用CDC的T-SQL跟踪字段更改

使用CDC或使用CDC的T-SQL跟踪字段更改
EN

Stack Overflow用户
提问于 2017-08-11 00:05:13
回答 2查看 630关注 0票数 0

下面是用于更新操作的CDC结果集。仅更新了area字段。

在上一次截图中,仅包含表中包含的部分sreenshot。字段要多得多。时不时地从他们的一些更新,一些不。在下面的查询中,我尝试在usable视图中按字段显示更改的统计信息。

代码语言:javascript
复制
with History AS (
SELECT
cz.GUID as Id, 
cz.category,
isnull(cz.area, 0) as area, 
isnull(cz.oilwidthmin,0) as oilwidthmin, 
isnull(cz.oilwidthmax,0) as oilwidthmax, 
isnull(cz.efectivwidthmin,0) as efectivwidthmin,
isnull(cz.efectivwidthmax,0) as efectivwidthmax,
isnull(cz.koafporistmin,0) as koafporistmin, 
isnull(cz.koafporistmax,0) as koafporistmax,
CASE cz.__$operation 
WHEN 1 THEN 'DELETE'
WHEN 2 THEN 'INSERT'
WHEN 3 THEN 'Before UPDATE'
WHEN 4 THEN 'After UPDATE'
END operation,
map.tran_begin_time as beginT, 
map.tran_end_time as endT
FROM cdc.fn_cdc_get_all_changes_dbo_EXT_GeolObject_KategZalezh(sys.fn_cdc_get_min_lsn('dbo_EXT_GeolObject_KategZalezh'), sys.fn_cdc_get_max_lsn(), 'all') AS cz 
INNER JOIN  [cdc].[lsn_time_mapping] map
    ON cz.[__$start_lsn] = map.start_lsn
)
SELECT  field, val, operation, beginT, endT FROM History
unpivot ( [val] for field in
(
--category,
area, 
oilwidthmin, 
oilwidthmax, 
efectivwidthmin, 
efectivwidthmax, 
koafporistmin, 
koafporistmax))t    where id = '2D166098-7CBD-4622-9EB0-000070506FE6'   

查询结果如下:

但是之前的结果包含额外的数据。预期结果必须如下:

我知道CDC按行跟踪更改。或许我错了?如果不是,我如何对SQL中的val字段进行一些比较。我对t-sql了解不深,我脑海中浮现的一切都被游标使用了。有什么想法吗?也许以某种方式使用CT (更改跟踪)?也许以某种方式使用group by

答案几乎是正确的。查询返回预期结果如下:

代码语言:javascript
复制
WITH History AS (
    SELECT
        *,
        CASE cz.__$operation 
            WHEN 1 THEN 'DELETE'
            WHEN 2 THEN 'INSERT'
            WHEN 3 THEN 'Before UPDATE'
            WHEN 4 THEN 'After UPDATE'
            END operation,
        map.tran_begin_time as beginT, 
        map.tran_end_time as endT
    FROM cdc.fn_cdc_get_all_changes_dbo_EXT_GeolObject_KategZalezh(sys.fn_cdc_get_min_lsn('dbo_EXT_GeolObject_KategZalezh'), sys.fn_cdc_get_max_lsn(), 'all') AS cz 
        INNER JOIN  [cdc].[lsn_time_mapping] map
            ON cz.[__$start_lsn] = map.start_lsn
    where cz.GUID = '2D166098-7CBD-4622-9EB0-000070506FE6'
),
UnpivotedValues AS(
    SELECT  guid, field, val, operation, beginT, endT 
    FROM History
        UNPIVOT ( [val] FOR field IN
        (
            area, 
            oilwidthmin, 
            oilwidthmax, 
            efectivwidthmin, 
            efectivwidthmax, 
            koafporistmin, 
            koafporistmax
        ))t
),
UnpivotedWithLastValue AS (
    SELECT 
        *,
        --Use LAG() to get the last value for the same field
        LAG(val, 1) OVER (PARTITION BY field ORDER BY BeginT) LastVal
    FROM UnpivotedValues
)
--Filter out record where the value equals the last value for the same field
SELECT * FROM UnpivotedWithLastValue WHERE val <> LastVal OR LastVal IS NULL ORDER BY guid

此查询的结果如下:

但是,当WHERE cz.GUID =不存在时,或者如果查询在WHERE谓词中使用了几个GUID,我会得到以下结果:

这是两个GUID的结果。第一行中LastVal的值必须为16691。比如第4行的val

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-08-11 20:12:11

不能将CDC设置为仅跟踪已更改的列的值。但是,您可以很容易地过滤出查询中未更改的值。

考虑以下查询,它是原始查询的简化副本:

代码语言:javascript
复制
WITH History AS (
    SELECT
        *,
        CASE cz.__$operation 
            WHEN 1 THEN 'DELETE'
            WHEN 2 THEN 'INSERT'
            WHEN 3 THEN 'Before UPDATE'
            WHEN 4 THEN 'After UPDATE'
            END operation,
        map.tran_begin_time as beginT, 
        map.tran_end_time as endT
    FROM cdc.fn_cdc_get_all_changes_Dbo_YourTable(sys.fn_cdc_get_min_lsn('Dbo_YourTable'), sys.fn_cdc_get_max_lsn(), 'all') AS cz 
        INNER JOIN  [cdc].[lsn_time_mapping] map
            ON cz.[__$start_lsn] = map.start_lsn
),
UnpivotedValues AS(
    SELECT id, field, val, operation, beginT, endT, t.tran_id
    FROM History
        UNPIVOT ( [val] FOR field IN
        (Column1, Column2, Column3))t
),
UnpivotedWithLastValue AS (
    SELECT 
        *,
        --Use LAG() to get the last value for the same field
        LAG(val, 1) OVER (PARTITION BY id, field ORDER BY BeginT) LastVal
    FROM UnpivotedValues
)
--Filter out record where the value equals the last value for the same field
SELECT * FROM UnpivotedWithLastValue WHERE val <> LastVal OR LastVal IS NULL
ORDER BY Id, beginT

在这个查询中,我使用了LAG()函数来获取每个字段的最后一个值。根据这个值,您可以过滤掉最终查询中未更改的记录,如上所示。

票数 1
EN

Stack Overflow用户

发布于 2017-08-11 17:45:38

在您的示例中,可以使用ROW_NUMBER函数对更改进行顺序编号-在此之后,可以将每个顺序更改与前一个更改(基于字段和id)连接在一起,并只输出具有diffent值的行。

如下所示:

代码语言:javascript
复制
WITH 
History AS 
(
SELECT
    cz.GUID as Id, 
    cz.category,
    isnull(cz.area, 0) as area, 
    isnull(cz.oilwidthmin,0) as oilwidthmin, 
    isnull(cz.oilwidthmax,0) as oilwidthmax, 
    isnull(cz.efectivwidthmin,0) as efectivwidthmin,
    isnull(cz.efectivwidthmax,0) as efectivwidthmax,
    isnull(cz.koafporistmin,0) as koafporistmin, 
    isnull(cz.koafporistmax,0) as koafporistmax,
    CASE 
        cz.__$operation 
        WHEN 1 THEN 'DELETE'
        WHEN 2 THEN 'INSERT'
        WHEN 3 THEN 'Before UPDATE'
        WHEN 4 THEN 'After UPDATE'
    END operation,
    map.tran_begin_time as beginT, 
    map.tran_end_time as endT,
    ROW_NUMBER() OVER (PARTITION BY cz.GUID ORDER BY map.tran_end_time ASC) as rn
FROM 
    cdc.fn_cdc_get_all_changes_dbo_EXT_GeolObject_KategZalezh(sys.fn_cdc_get_min_lsn('dbo_EXT_GeolObject_KategZalezh'), sys.fn_cdc_get_max_lsn(), 'all') AS cz 
INNER JOIN  
    [cdc].[lsn_time_mapping] map ON cz.[__$start_lsn] = map.start_lsn
),

History2 AS
(
    SELECT  id, field, val, operation, beginT, endT, rn FROM History
    unpivot ( [val] for field in
    (
    --category,
    area, 
    oilwidthmin, 
    oilwidthmax, 
    efectivwidthmin, 
    efectivwidthmax, 
    koafporistmin, 
    koafporistmax))t    
    where id = '2D166098-7CBD-4622-9EB0-000070506FE6'
)

-- return the values that were inserted first
SELECT
    a.*
FROM
    History2 a
WHERE 
    a.rn=1

UNION ALL

-- ... and then return only the values that are different from the previous ones
SELECT
    a.*
FROM
    History2 a
INNER JOIN
    History2 b ON a.id = b.id AND a.field=b.field AND a.rn = b.rn-1 AND a.value<>b.value
WHERE
    a.rn>1

顺便说一下,您还可以将CDC配置为仅跟踪某些列的更改,而不是整个表。查看sys.sp_cdc_enable_table存储过程的@captured_column_list。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45618566

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档