1

我在 SQL Server 中编写了一个存储过程。基本上它会尝试处理 SCD2。我正在尝试做三件事:

  1. 当目标不匹配时,插入记录
  2. 当源不匹配时,停用活动记录(更新)
  3. 匹配时,将活动记录标志更新为 N

这 3 种情况正在得到妥善处理。

我的问题是匹配时我还需要在源中插入一条新记录。我有一些文章建议使用$output子句并在上面插入MERGE;我试过了,但我得到了这个错误:

消息 356,级别 16,状态 1,过程 myscd2,第 17
行当 FROM 子句包含嵌套的 INSERT 时,INSERT 语句的目标表“dbo.dimproducts”不能位于(主键、外键)关系的任一侧, UPDATE、DELETE 或 MERGE 语句。找到参考约束“FK_FactSalesOrders_DimProducts”。

请在下面查看我的代码并告诉我,我可以做些什么来解决这个问题:

begin
    insert into dbo.dimproducts(ProductID, ProductName, StandardListPrice, ProductSubCategoryID, ProductSubCategoryName, ProductCategoryID, ProductCategoryName, active_flag)   
        select 
            productid, name, ListPrice, 
            productsubcategoryid, ProductSubCategoryName,
            ProductCategoryID, ProductCategoryName, Active_Flag 
        from
            (merge dbo.dimproducts as tgt
             using AdventureWorks_Basics.dbo.Products as src on (tgt.productid = src.productid)
             when matched and src.name != tgt.productname and tgt.active_flag = 'Y'
                then 
                   update set tgt.active_flag = 'N'
             when not matched by target
                then 
                   insert(ProductID, ProductName, StandardListPrice, ProductSubCategoryID, ProductSubCategoryName, ProductCategoryID, ProductCategoryName, active_flag)
                   values (src.productid, src.name, src.listprice, 100, 'ABC', 101, coalesce(src.productline, 'XYZ'), 'Y')
             when not matched by source
                then 
                   update set tgt.active_flag = 'N'
             OUTPUT $action AS Action, src.productid, src.name, src.listprice, 100 as productsubcategoryid, 'ABC' as ProductSubCategoryName, 101 as ProductCategoryID, coalesce(src.productline, 'XYZ') as ProductCategoryName, 'Y' as Active_Flag) AS MergeOutput
        where
            MergeOutput.Action = 'UPDATE';
4

2 回答 2

0

该子句有一个限制,OUTPUT即目标不能具有 FOREIGN KEY 约束,或者被 FOREIGN KEY 约束引用。因此你得到的错误。

但是,您可以执行以下操作,从输出子句将数据插入临时表,然后从临时表中选择以插入目标表。

警告我仍然建议您避免使用MERGE语句并阅读文章的原因。

CREATE TABLE #dimproducts (
 Act                        VARCHAR(10)
,ProductID                  INT
,ProductName                VARCHAR(100)
,StandardListPrice          INT
,ProductSubCategoryID       INT
,ProductSubCategoryName     VARCHAR(100)
,ProductCategoryID          INT
,ProductCategoryName        VARCHAR(100)
,active_flag                VARCHAR(1));

merge dbo.dimproducts as tgt
    using  AdventureWorks_Basics.dbo.Products as src    on (tgt.productid = src.productid)

when matched and src.name != tgt.productname and tgt.active_flag = 'Y'then 
    update set tgt.active_flag = 'N'

when not matched by target then 
    insert(ProductID,ProductName,StandardListPrice,ProductSubCategoryID,ProductSubCategoryName,ProductCategoryID,ProductCategoryName,active_flag)
    values(src.productid,src.name,src.listprice,100,'ABC',101,coalesce(src.productline,'XYZ'),'Y')

when not matched by source then
    update set tgt.active_flag = 'N'

    OUTPUT $action AS Action, src.productid,src.name,src.listprice,100 as productsubcategoryid,'ABC' as ProductSubCategoryName
                    ,101 as ProductCategoryID,coalesce(src.productline,'XYZ') as ProductCategoryName,'Y' as Active_Flag
    INTO #dimproducts (Act,ProductID,ProductName,StandardListPrice,ProductSubCategoryID,ProductSubCategoryName,ProductCategoryID,ProductCategoryName,active_flag);

INSERT INTO dbo.dimproducts (productid,name,ListPrice,productsubcategoryid,ProductSubCategoryName,ProductCategoryID,ProductCategoryName,Active_Flag)
select productid,name,ListPrice,productsubcategoryid,ProductSubCategoryName,ProductCategoryID,ProductCategoryName,Active_Flag 
FROM #dimproducts
WHERE Act = 'UPDATE';
于 2018-02-10T23:13:18.293 回答
0

http://www.sqlservercentral.com/articles/MERGE/73805/

使用 T-SQL MERGE 缓慢更改维度 作者:Adam Aspin,2011 /06/20
请参阅:Type 2 SCD - 将先前属性的历史记录为单独的记录,指示它们的有效日期,并标记当前有效的记录

它基本上是 M.Ali 的答案,其中包含更多信息以及有关 SCD 1、3 和 4 的信息:

于 2019-02-28T18:49:13.923 回答