5

サインアップフォームで扱っているテーブルは、[months]、[members]、[months_members]の3つです。最後の1つは、単なる結合テーブルです。彼らはこのように見えます:

[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

したがって、1つのテーブルに挿入します[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 に答える