我在SQL Server中编写了一个存储过程。基本上它试图处理SCD2。我想做的三件事:
正在妥善处理这三种情况。
我的问题是匹配时我需要在源代码中插入新记录。我有一篇文章建议使用$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';
答案 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的信息: