我在 mssql 服务器中有 2 个表。我可以通过自定义插入/更新/删除以及 Merge 语句执行 scd。
我想知道是否有任何通用程序可以达到目的。我们只传给它 2 个表,它应该能支持 SCD。SQL Server 2008 中的任何选项?谢谢
不,无论您传递给它什么表,都没有也不能有一个通用的适合。有几个原因:
这不是不可能的原因,但也要考虑:对于一个适当的UPSERT
通常与临时表一起使用的语句,该MERGE
语句对于 SCD 来说很糟糕,除非在特殊情况下。那是因为您不能将MERGE
语句与 an 一起使用,INSERT/UPDATE
并且您必须为此禁用外键,因为 anUPDATE
被实现为DELETE THEN INSERT
(或类似的东西,不记得清楚了,但是当我尝试时遇到了这些问题) .
我更喜欢这样做(SCD 类型 2 和 SQL Server):
步骤1:
IF EXISTS (
SELECT * FROM sys.objects
WHERE name = 'tmpDimSource')
DROP TABLE tmpDimSource;
SELECT
*
INTO tmpDimSource
FROM
(
SELECT whatever
FROM yourTable
);
第2步:
IF EXISTS (
SELECT * FROM sys.objects
WHERE name = 'tmpDimYourDimensionName')
DROP TABLE tmpDimYourDimensionName;
SELECT * INTO tmpDimYourDimensionName FROM D_yourDimensionName WHERE 1 = 0;
INSERT INTO tmpDimYourDimensionName
(
sid, /*a surrogate id column*/
theColumnsYouNeedInYourDimension,
validFrom
)
SELECT
ISNULL(d.sid, 0),
ds.theColumnsYouNeedInYourDimension,
DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0) /*the current date*/
FROM
tmpDimSource ds
LEFT JOIN D_yourDimensionName d ON ds.whateverId = c.whateverId
;
第ISNULL(d.sid, 0)
2 步很重要。如果条目已存在,则返回维度的代理 ID,否则返回 0。
第 3 步:
UPDATE D_yourDimensionName SET
validTo = DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()) - 1, 0) /*yesterday*/
FROM
D_yourDimensionName d
INNER JOIN tmpDimYourDimensionName t ON d.sid = t.sid
WHERE t.sid <> 0 AND
(
d.theColumnWhichHasChangedAndIsImportant <> t.theColumnWhichHasChangedAndIsImportant OR
d.anotherColumn <> t.anotherColumn
)
;
在第 3 步中,您将现有条目标记为不再有效并保留它的历史记录。您获得的有效条目WHERE validTo IS NULL
.
如果需要,您还可以添加另一个UPDATE
以用新值覆盖任何其他列。
第4步:
INSERT INTO D_yourDimensionName
SELECT * FROM tmpDimYourDimensionName
WHERE sid = 0;
就是这样。