5

我要为注册表单处理三个表:[months]、[members] 和 [months_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_members]表中。而且我还想从[months_members]表中删除子查询中存在的任何内容——但前提它对应于当年的一个月。如果子查询中没有对应于不同年份的数据,我不想删除它。我想不理会那些历史数据。所以条件是踢球者。USINGUSINGDATEPART

所以我要插入一张桌子,[months_members]但我也需要它来了解这张[months]桌子。有没有办法做到这一点?或者我是否必须让步并遍历多个 SQL 查询?

4

1 回答 1

8

您可以使用 CTE 代替目标表(或视图)。SQL Server 可以通过 CTE/视图跟踪更新。这是一个被破解的演示:

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;
于 2013-02-07T15:49:39.197 回答