使用SQL Merge或UPDATE / INSERT

时间:2013-04-14 21:40:23

标签: sql sql-server-2012

我有一个表(Customer_Master_File),需要从转储到文件夹中的平面文件进行更新。我有一个SSIS包,用于获取平面文件并将它们导入临时表(temp_Customer_Master_File)

我无法做到的是:

对于临时表中的每条记录,如果主表中存在Customer_Number,则更新它,如果没有插入临时表的内容。

我正在更新记录的所有字段,而不是查找单个字段更改。

我尝试了SQL Merge函数,但是当源数据中有多个记录时,它会出错。

平面文件包含对客户记录的更改,并且一次可能有多个更改。我只想根据需要插入或更新每个记录。

我还尝试从TEMP_TABLE中执行INSERT INTO MASTER_FILE,而不是MASTER_FILE中的CUSTOMER_NUMBER,但是当它遇到重复的源行时,它也会因PK错误而失败。

1 个答案:

答案 0 :(得分:3)

UPDATE m SET 
  col2 = t.col2, 
  col3 = t.col3 -- etc. - all columns except Customer_Number
FROM dbo.Master_File AS m
INNER JOIN 
(
  SELECT 
    Customer_Number, rn = ROW_NUMBER() OVER
    (
      PARTITION BY Customer_Number ORDER BY [timestamp_column] DESC
    ), col2, col3, ... etc ...
  FROM dbo.Temp_Table
) AS t
ON m.Customer_Number = t.Customer_Number
WHERE t.rn = 1;

INSERT dbo.Master_File(Customer_Number, col2, col3, ...etc...)
  SELECT Customer_Number, col2, col3, ...etc...
  FROM 
  (
    SELECT 
      Customer_Number, rn = ROW_NUMBER() OVER 
      (
        PARTITION BY Customer_Number ORDER BY [timestamp_column DESC
      ),
      col2, col3, ...etc...
    FROM dbo.Temp_Table AS t 
    WHERE NOT EXISTS 
    (
      SELECT 1 FROM dbo.Master_File AS m
      WHERE m.Customer_Number = t.Customer_Number
    )
  ) AS x WHERE rn = 1;

这将处理源表中目标中尚不存在的多行。我已经对列名进行了假设,你必须调整它们。

MERGE可能很诱人,但有几个原因让我回避它:

  1. 语法难以记忆......
  2. you don't get any more concurrency than the above approach unless you intentionally add specific locking hints ...
  3. there are many unresolved bugs with MERGE可能还有更多尚未发现......
  4. I recently published a cautionary tip here as well