Sql 如何在MERGE-INTO语句中使用连接?

Sql 如何在MERGE-INTO语句中使用连接?,sql,sql-server,sql-server-2008,tsql,merge,Sql,Sql Server,Sql Server 2008,Tsql,Merge,我正在处理三个表格作为注册表单:[months]、[members]和[months\u members]。最后一个只是一个联接表。它们看起来像这样: [months] ======== [id] INT (Primary Key) [name] VARCHAR(50) [date] DATE [members] ========= [id] INT (Primary Key) [fname] VARCHAR(50) [lname] VARCHAR(50) [email] VARCHAR(30

我正在处理三个表格作为注册表单:[months]、[members]和[months\u members]。最后一个只是一个联接表。它们看起来像这样:

[months]
========
[id] INT (Primary Key)
[name] VARCHAR(50)
[date] DATE

[members]
=========
[id] INT (Primary Key)
[fname] VARCHAR(50)
[lname] VARCHAR(50)
[email] VARCHAR(300)

[months_members]
================
[id] INT (Primary Key)
[month_id] INT
[member_id] INT
所以,从概念上讲,非常简单。有一个固定的成员名单,他们可以在特定的月份注册。我的表单允许他们注册不同的月份,实际上允许管理员输入或更改!一次完成所有注册。因此,我希望使用MERGE语句通过一个查询将数据输入数据库,而不是通过多次查询进行迭代

下面是我开始写的内容,尽管我知道这不是正确的语法:

MERGE INTO [months_members] mm
INNER JOIN [months] mo ON mo.[id] = mm.[month_id] 
USING (
    SELECT 1 AS [month_id], 1 AS [member_id] UNION ALL
    SELECT 2 AS [month_id], 3 AS [member_id] UNION ALL
    SELECT 4 AS [month_id], 4 AS [member_id]
) AS u ON mm.[month_id] = u.[month_id] AND mm.[member_id] = u.[member_id] 
WHEN NOT MATCHED THEN 
    INSERT ([month_id], [member_id]) VALUES (u.[month_id], u.[member_id]) 
WHEN NOT MATCHED BY SOURCE AND DATEPART(YEAR, mo.[start]) = 2013 THEN 
    DELETE;
希望这能说明我遇到的问题。我想将USING子查询中的任何新数据插入到[months\u members]表中。我还想从[months_members]表中删除USING子查询中不存在的任何内容,但前提是它对应于当前年份中的一个月。如果USING子查询中没有与不同年份对应的数据,我不想删除该数据。我不想谈历史数据。所以DATEPART条件是kicker


因此,我将插入到一个表中,[months_members],但我还需要它知道[months]表。有没有办法做到这一点?或者我必须承认并迭代许多SQL查询吗?

您可以使用CTE代替目标表或视图。SQL Server可以通过CTE/view跟踪更新。这是一个拼凑在一起的演示:

SELECT *
INTO #temp
FROM sys.objects
GO

;WITH cte AS (
    SELECT t1.*
    FROM #temp t1
    JOIN #temp t2 ON t1.object_id = t2.object_id
)
MERGE cte USING (
    SELECT 1 AS [month_id], 1 AS [member_id] UNION ALL
    SELECT 2 AS [month_id], 3 AS [member_id] UNION ALL
    SELECT 4 AS [month_id], 4 AS [member_id]
) AS u ON cte.object_id = u.[month_id]
WHEN MATCHED THEN DELETE;

如果CTE中有多个表,它会在匹配时从中删除哪个表?使用select list和from子句显示它从from子句中获取表,就像使用其他类似DML的delete一样,您可以在不使用CTE的情况下内联编写联接。我还没有看到这方面的文件,但我很有信心这是一条规则。依我看,这是可以信赖的保证行为。CTE和视图作为合并的目标是不能互换的。我以前从未使用过CTE!他们太棒了!谢谢,这就成功了。我也从来没有用过CTE——我看不出上面的内容会如何插入新的值?我刚刚删除了一个我尝试过的答案。我想我已经意识到了,在一个查询中需要两个不匹配的条件。我不知道你会怎么做。将一个删除步骤和一个插入步骤全部放在一个存储过程中真的是一种负担吗?这不是一种负担,但我只是好奇是否有一种优雅的方法可以在一个步骤中完成它。对我来说,这就是合并语法的全部要点:用一个查询替换两个查询。