没有源表的 SQL Server MERGE

Posted

技术标签:

【中文标题】没有源表的 SQL Server MERGE【英文标题】:SQL Server MERGE without a source table 【发布时间】:2017-03-21 15:01:36 【问题描述】:

我正在学习如何从这个页面使用 SQL Server MERGE 语句: https://technet.microsoft.com/en-us/library/bb522522(v=sql.105).aspx

MERGE dbo.FactBuyingHabits AS Target
USING (SELECT CustomerID, ProductID, PurchaseDate FROM dbo.Purchases) AS Source
    ON (Target.ProductID = Source.ProductID AND Target.CustomerID = Source.CustomerID)

WHEN MATCHED THEN
    UPDATE SET Target.LastPurchaseDate = Source.PurchaseDate

WHEN NOT MATCHED BY TARGET THEN
    INSERT (CustomerID, ProductID, LastPurchaseDate)
    VALUES (Source.CustomerID, Source.ProductID, Source.PurchaseDate)

OUTPUT $action, Inserted.*, Deleted.*;

但是,我能找到的所有示例(例如上面的示例)都使用实际表作为源。是否可以直接传递数据?我宁愿不为此创建一个临时表(如果可能并推荐?) 如何修改上面的查询?

谢谢

【问题讨论】:

在您学习如何使用合并时,您是否想直接传递数据只是为了练习目的? 不,我正在考虑允许用户更新/插入数据,而不必每次都创建一个新表......这不推荐吗?否则,如果 2 个用户尝试同时合并,我需要有规则来创建唯一的临时表名称,它开始变得一团糟。 您不需要管理临时表的命名。 SQL Server 自动确保创建同名临时表的多个会话不会发生冲突。 sqlteam.com/article/temporary-tables 不需要为不同的用户创建唯一的临时表,只需使用本地临时表使用 # 它不会在另一个事务中找到。如果两个用户输入相同的记录,sql也会管理。 【参考方案1】:

你可以这样做:

Declare @customerID int = 1;
Declare @productID int = 1;
Declare @purchaseDate date = '1900-01-01';

MERGE dbo.FactBuyingHabits AS Target
USING (SELECT CustomerID = @customerID, 
    ProductID = @productID, 
    PurchaseDate = @purchaseDate) AS Source
  ON (Target.ProductID = Source.ProductID AND Target.CustomerID = Source.CustomerID)
  WHEN MATCHED THEN
    UPDATE SET Target.LastPurchaseDate = Source.PurchaseDate
  WHEN NOT MATCHED BY TARGET THEN
    INSERT (CustomerID, ProductID, LastPurchaseDate)
    VALUES (Source.CustomerID, Source.ProductID, Source.PurchaseDate)
OUTPUT $action, Inserted.*, Deleted.*;

【讨论】:

【参考方案2】:

试试这个格式:

MERGE TARGET_TABLE AS I
USING (VALUES ('VALUE1','VALUE2')) as s(COL1,COL2)
ON I.COL1 = s.COL1
WHEN MATCHED THEN

你也可以参考这个: "Merge" style operation with literal values?

【讨论】:

【参考方案3】:

我需要一个更简单的版本,于是想到了这个解决方案:

MERGE Target_Table
USING (VALUES (0)) as s(x)
ON last_run is not null
WHEN not matched then
insert (last_run) values(getdate())
when matched then
update set last_run=getDate();

【讨论】:

以上是关于没有源表的 SQL Server MERGE的主要内容,如果未能解决你的问题,请参考以下文章

sql server中的merge

sql server 2008 merge matched判定条件

SQL Server中的Merge Into

SQL Server中的Merge关键字

SQL Server中的Merge关键字

sql server 2008中“Merge”子句的性能如何?