2014-09-26 36 views
0

由於我注意到我無法在SSIS中使用SCD,因爲我有大量數據,所以我試圖用T-SQL構建慢速變化維表。在SQL Server中使用MERGE語句管理緩慢更改維度

我需要你的幫助

我的表結構:

CREATE TABLE [dbo].[Customer] 
(
    [BusinessEntityID] [int] PRIMARY KEY NOT NULL, 
    [FirstName] [nvarchar](50) NULL, 
    [MiddleName] [nvarchar](50) NULL, 
    [LastName] [nvarchar](50) NULL, 
    [EmailAddress] [nvarchar](50) NULL, 
    [AddressLine1] [nvarchar](60) NULL, 
    [AddressLine2] [nvarchar](60) NULL, 
    [City] [nvarchar](30) NULL, 
    [PostalCode] [nvarchar](15) NULL, 
    [CountryRegionCode] [nvarchar](3) NULL, 
    [Country] [nvarchar](50) NULL, 
    [StateProvince] [nvarchar](50) NULL 
) 

CREATE TABLE [dbo].[DimCustomer] 
(
    [CustomerKey] int IDENTITY (1,1) PRIMARY KEY CLUSTERED, 
    [BusinessEntityID] int NOT NULL, 
    [FirstName] nvarchar(50) NULL, 
    [MiddleName] nvarchar(50) NULL, 
    [LastName] nvarchar(50) NULL, 
    [EmailAddress] nvarchar(50) NULL, 
    [AddressLine1] nvarchar(60) NULL, 
    [AddressLine2] nvarchar(60) NULL, 
    [City] nvarchar(30) NULL, 
    [PostalCode] nvarchar(15) NULL, 
    [CountryRegionCode] nvarchar(3) NULL, 
    [Country] nvarchar(50) NULL, 
    [StateProvince] nvarchar(50) NULL, 
    [StartDate] Datetime NULL, 
    [EndDate] Datetime NULL, 
    [CurrentFlag] Char(1) 
) 

合併聲明:

MERGE INTO dbo.DimCustomer Dest 
USING dbo.Customer Src ON (Dest.BusinessEntityID = Src.BusinessEntityID) 

WHEN MATCHED AND Dest.FirstName != Src.FirstName 
    THEN 
    UPDATE SET Dest.FirstName = Src.FirstName; 

USE BART_DEV 
GO 
MERGE INTO dbo.DimCustomer Dest 
USING dbo.Customer Src ON (Dest.BusinessEntityID = Src.BusinessEntityID) 

WHEN MATCHED AND Dest.MiddleName != Src.MiddleName 
    THEN 
    UPDATE SET Dest.MiddleName = Src.MiddleName; 

USE BART_DEV 
GO 
MERGE INTO dbo.DimCustomer Dest 
USING dbo.Customer Src ON (Dest.BusinessEntityID = Src.BusinessEntityID) 

WHEN MATCHED AND Dest.LastName != Src.LastName 
    THEN 
    UPDATE SET Dest.LastName = Src.LastName; 

到目前爲止,上面的語句工作正常但是底部聲明不起作用。

USE BOB_DEV 
GO 
INSERT INTO dbo.DimCustomer ([BusinessEntityID],[FirstName],[MiddleName], [LastName],[AddressLine1], [AddressLine2], [City], [PostalCode], [CountryRegionCode], [Country], [StateProvince], [StartDate], [EndDate], [CurrentFlag]) 
    SELECT 
     [BusinessEntityID], [FirstName], [MiddleName], [LastName], 
     [AddressLine1], [AddressLine2], [City], [PostalCode], [CountryRegionCode], 
     [Country], [StateProvince], [StartDate], [EndDate], [CurrentFlag] 
    FROM 
     (MERGE dbo.DimCustomer TT 
     USING dbo.Customer ST ON (TT.BusinessEntityID = ST.BusinessEntityID) 

     WHEN NOT MATCHED THEN 
      INSERT ([BusinessEntityID], [FirstName], [MiddleName], [LastName], 
        [AddressLine1], [AddressLine2], [City], [PostalCode], 
        [CountryRegionCode], [Country], [StateProvince], 
        [StartDate], [EndDate], [CurrentFlag]) 
      VALUES ([BusinessEntityID], [FirstName], [MiddleName], [LastName], 
        [AddressLine1], [AddressLine2], [City], [PostalCode], 
        [CountryRegionCode], [Country], [StateProvince], 
        '01/01/1900', NULL, '0') 

     WHEN NOT MATCHED AND TT.CurrentFlag = 'Y' AND (ISNULL(TT.AddressLine1, '') != ISNULL (ST.AddressLine1,'')) 
     THEN 
      UPDATE SET TT.CurrentFlag = 'N', TT.EndDate = GETDATE() -1 

     WHEN NOT MATCHED AND TT.CurrentFlag = 'Y' AND (ISNULL(TT.AddressLine2, '') != ISNULL (ST.AddressLine2,'')) 
     THEN 
      UPDATE SET TT.CurrentFlag = 'N', TT.EndDate = GETDATE() -1 

     WHEN NOT MATCHED AND TT.CurrentFlag = 'Y' AND (ISNULL(TT.City, '') != ISNULL (ST.City,'')) 
     THEN 
      UPDATE SET TT.CurrentFlag = 'N', TT.EndDate = GETDATE() -1 

     WHEN NOT MATCHED AND TT.CurrentFlag = 'Y' AND (ISNULL(TT.PostalCode, '') != ISNULL (ST.PostalCode,'')) 
     THEN 
      UPDATE SET TT.CurrentFlag = 'N', TT.EndDate = GETDATE() -1 

     WHEN NOT MATCHED AND TT.CurrentFlag = 'Y' AND (ISNULL(TT.CountryRegionCode, '') != ISNULL (ST.CountryRegionCode,'')) 
     THEN 
      UPDATE SET TT.CurrentFlag = 'N', TT.EndDate = GETDATE() -1 

     WHEN NOT MATCHED AND TT.CurrentFlag = 'Y' AND (ISNULL(TT.Country, '') != ISNULL (ST.Country,'')) 
     THEN 
      UPDATE SET TT.CurrentFlag = 'N', TT.EndDate = GETDATE() -1 

     WHEN NOT MATCHED AND TT.CurrentFlag = 'Y' AND (ISNULL(TT.StateProvince, '') != ISNULL (ST.StateProvince,'')) 
     THEN 
      UPDATE SET TT.CurrentFlag = 'N', TT.EndDate = GETDATE() -1 

     OUTPUT $Action Action_Taken, ST.BusinessEntityID, ST.FirstName, ST.MiddleName, ST.LastName, ST.AddressLine1, ST.AddressLine2, ST.City, ST.PostalCode, ST.CountryRegionCode, ST.Country, ST.StateProvince, GETDATE() AS EndDate, NULL AS EndDate, 'Y' AS CurrentFlag 
) 
AS MERGE_OUT 
WHERE MERGE_OUT.Action_Taken = 'UPDATE'; 
GO 
SELECT * FROM dbo.DimCustomer 

不過,我收到此錯誤信息:

消息10710,級別15,狀態1,行15
型 '更新' 的作用是不允許在「WHEN NOT MERGE聲明的「MATCHED」條款。

我不知道如何解決這個錯誤信息。

+3

那麼,錯誤似乎很明顯:既然你不** **與目標表中現有的行匹配,你** CAN NOT **使用' UPDATE'語句 - 畢竟,沒有匹配的行要更新!在這種情況下,您需要使用'INSERT'! – 2014-09-26 19:27:56

+0

你能更具體嗎?你能用我的sql語句給我看一個例子嗎? – Pabartho 2014-09-26 19:30:39

+2

WHEN NOT MATCHED AND TT.CurrentFlag ='Y'AND(ISNULL(TT.AddressLine1,'')!= ISNULL(ST.AddressLine1,''))THEN UPDATE SET TT.CurrentFlag ='N',TT.EndDate = GETDATE()-1 – Paparazzi 2014-09-26 19:33:53

回答

1

你需要從WHEN NOT MATCHED子句刪除UPDATE語句通過@marc_s

你可以做一個選擇和按摩currentflag的建議的基礎上,所有這些條件,結束日期,使之作爲源表,而不只是客戶。

這裏是片段

USING 
    (
     select ST.[BusinessEntityID], ST.[FirstName], ST.[MiddleName], ST.[LastName], 
       ST.[AddressLine1], ST.[AddressLine2], ST.[City], ST.[PostalCode], 
       ST.[CountryRegionCode], ST.[Country], ST.[StateProvince], 
       ST.[StartDate], 
       (CASE WHEN ST.CurrentFlag ='Y' AND (ISNULL(TT.AddressLine1, '') != ISNULL (ST.AddressLine1,'')) 
         OR 
         ST.CurrentFlag = 'Y' AND (ISNULL(TT.AddressLine2, '') != ISNULL (ST.AddressLine2,'')) 
        THEN GETDATE() -1 ELSE ST.EndDate 
       ..... 
      ) as [EndDate], 
       (CASE WHEN ST.CurrentFlag ='Y' AND (ISNULL(TT.AddressLine1, '') != ISNULL (ST.AddressLine1,'')) 
        OR 
        ST.CurrentFlag = 'Y' AND (ISNULL(TT.AddressLine2, '') != ISNULL (ST.AddressLine2,'')) 
        THEN 'N' ELSE ST.CurrentFlag 
        END 
      ) as CurrentFlag      
     dbo.Customer ST 
     INNER JOIN DimCustomer TT 
     ON TT.BusinessEntityID = ST.BusinessEntityID 



    ) 
    ON (TT.BusinessEntityID = ST.BusinessEntityID) 
+0

這是第一條語句行的答案嗎? – Pabartho 2014-09-26 20:10:47

+0

@Pabartho,我看到你想插入currentFlags和enddate基於一些條件,你當前的源表只是Dbo.customer,而不是你可以使用選擇像我貼 – radar 2014-09-26 20:16:20