1

我在 mssql 服务器中有 2 个表。我可以通过自定义插入/更新/删除以及 Merge 语句执行 scd。

我想知道是否有任何通用程序可以达到目的。我们只传给它 2 个表,它应该能支持 SCD。SQL Server 2008 中的任何选项?谢谢

4

1 回答 1

1

不,无论您传递给它什么表,都没有也不能有一个通用的适合。有几个原因:

  • 您怎么知道 SCD 类型?(好吧,可能是另一个参数,但是......)
  • 你怎么知道哪一列应该被历史化,哪一列应该被覆盖?
  • 如何确定哪一列是业务键、代理键、到期列等等?
  • 要在更新语句中指定列,您必须编写动态 sql,这是可能的,但上述要点发挥了作用

这不是不可能的原因,但也要考虑:对于一个适当的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;

就是这样。

于 2013-01-29T11:02:58.703 回答