【发布时间】:2019-06-23 01:58:53
【问题描述】:
我对这个 MERGE 声明感到惊讶,该公司并没有真正做到 Type 2 Slowing Change Dimension,而是接近了。奇怪的是,它甚至不是分析数据,但让我们忽略这个可怕的决定。我有这个工作引用HashBytes 来指示更改的行。不幸的是,为了解决所有场景,我最终从实际保存更新行的临时表中获得了额外的INSERT。
唉,它很实用,但如果你有更有效的设计,请分享。我会很感激。
但是,我试图从Temp 表中获取一个row count,不仅代表INSERT,而且更新和新的INSERTS,都是具有自己row count 的不同的独立操作,我需要记录和说明。
请问我该怎么做?
DECLARE @dtNow AS DATETIME = GetDate()
DECLARE @dtPast AS DATETIME = DATEADD(day,-1,GetDate())
DECLARE @dtFuture AS DATETIME = '22991231'
SET NOCOUNT ON;
-- Temp Table is JUST Updating Rows reflecting
--Historical Marker on existing row No content change to row's columnar content data
IF OBJECT_ID('tempdb..#TheTempTableName') IS NOT NULL DROP TABLE #TheTempTableName
CREATE TABLE #TheTempTableName
(
ABunchOfColumns
RowCreatedDate datetime NULL,
RowEffectiveDate datetime NULL,
RowTerminationDate datetime NULL,
RowIsCurrent bit NULL,
RowHash varchar(max) NULL,
)
INSERT INTO #TheTempTableName
(
ABunchOfColumns
,RowCreatedDate
,RowEffectiveDate
,RowTerminationDate
,RowIsCurrent
,RowHash
)
SELECT
ABunchOfColumns
,RowCreatedDate
,RowEffectiveDate
,RowTerminationDate
,RowIsCurrent
,RowHash
FROM
(
MERGE tblDim WITH (HOLDLOCK) AS target
USING
(
SELECT
ABunchOfColumns
,RowCreatedDate
,RowEffectiveDate
,RowTerminationDate
,RowIsCurrent
,RowHash
FROM dbo.tblStaging
)
AS source
ON target.PKID = source.PKID
WHEN MATCHED
AND target.RowIsCurrent = 1
AND target.RowHash != source.RowHash
------- PROCESS ONE -- UPDATE --- HISTORICALLY MARK EXISTING ROWS
THEN UPDATE SET
RowEffectiveDate = @dtPast
,RowTerminationDate = @dtPast
,RowIsCurrent = 0
----- PROCESS TWO -- INSERT ---INSERT NEW ROWS
WHEN NOT MATCHED
THEN INSERT --- THIS INSERT Goes directly into Target ( DIM ) Table (New Rows not matched with PK = PK )
(
ABunchOfColumns
,RowCreatedDate
,RowEffectiveDate
,RowTerminationDate
,RowIsCurrent
,RowHash
)
VALUES
(
source.ABunchOfColumns
,@dtNow --source.RowCreatedDate,
,@dtFuture ---source.RowEffectiveDate,
,@dtFuture ---source.RowTerminationDate,
,1 ---source.RowIsCurrent,
,source.RowHash
)
-------PROCESS THREE a -- INSERT ---OUTPUT MATCHED ROWS FROM PROCESS ONE THAT CAUSED HISTORICAL MARK (CHANGES) "INSERT"
OUTPUT
$action Action_Out,
ABunchOfColumns
,RowCreatedDate
,RowEffectiveDate
,RowTerminationDate
,RowIsCurrent
,RowHash
)
AS MERGE_OUT
WHERE MERGE_OUT.Action_Out = 'UPDATE';
----------PROCESS THREE b -- INSERT FROM Temp Tbl to final
--Now we flush the data in the temp table into dim table
INSERT INTO tblDim
(
ABunchOfColumns
,RowCreatedDate
,RowEffectiveDate
,RowTerminationDate
,RowIsCurrent
,RowHash
)
SELECT
ABunchOfColumns
,@dtNow AS RowCreatedDate
,@dtFuture AS RowEffectiveDate
,@dtFuture AS RowTerminationDate
,1 AS RowIsCurrent
,RowHash
FROM #TheTempTableName
END
【问题讨论】:
-
希望您知道,您可以使用更简单的代码和单独的 INSERT/UPDATE 语句来做同样的事情。我个人避免使用 MERGE,这是一个原因:mssqltips.com/sqlservertip/3074/… 最后请注意,任何散列算法都可能发生冲突(两组不同的数据导致相同的散列)。因此,在回答“更有效的设计”时,我建议单独插入/更新,但这实际上只是关于是否更有效的意见
标签: sql sql-server merge ssis etl