我有三张桌子正在处理注册表格:[月],[会员]和[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]
子查询中 not 的USING
表中删除任何内容 - 但只有当它对应于时才会删除当年的一个月。如果USING
子查询中不存在与不同年份对应的数据,我不想删除它。我想单独保留这些历史数据。所以DATEPART
条件是踢球者。
所以我插入一个表[months_members]
,但我还需要它知道[months]
表。有没有办法实现这个目标?或者我是否必须承认并迭代一些SQL查询?
答案 0 :(得分:5)
您可以使用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;