如何在SQL Server中匹配条件时更新和插入新记录

时间:2018-02-10 22:30:49

标签: sql-server sql-server-2008 stored-procedures scd2

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

  1. 如果未与目标匹配,请插入记录
  2. 如果未与来源匹配,请取消激活活动记录(更新)
  3. 匹配时,将活动记录标志更新为N
  4. 正在妥善处理这三种情况。

    我的问题是匹配时我需要在源代码中插入新记录。我有一篇文章建议使用$output子句并在MERGE之上插入;我试了但是我收到了这个错误:

      

    Msg 356,Level 16,State 1,Procedure myscd2,Line 17
      当FROM子句包含嵌套的INSERT,UPDATE,DELETE或MERGE语句时,INSERT语句的目标表'dbo.dimproducts'不能位于(主键,外键)关系的任何一侧。找到参考约束'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';
    

2 个答案:

答案 0 :(得分:0)

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

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

警告我仍然建议您避免使用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';

答案 1 :(得分:0)

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

使用T-SQL MERGE缓慢更改尺寸 作者亚当·阿斯平(Adam Aspin),2011/06/20
请参阅部分:类型2 SCD-将以前的属性的历史记录作为单独的记录,指出它们的有效日期,并标记当前有效的记录

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