次の名前のデータを含むテーブルがありますenergydata
たった3列です
(webmeterID, DateTime, kWh)
テーブルに更新されたデータの新しいセットがありますtemp_energydata
。
DateTime
とはwebmeterID
同じままです。ただし、kWh
値はテーブルから更新する必要がありtemp_energydata
ます。
このためのT-SQLを正しい方法で作成するにはどうすればよいですか?
次の名前のデータを含むテーブルがありますenergydata
たった3列です
(webmeterID, DateTime, kWh)
テーブルに更新されたデータの新しいセットがありますtemp_energydata
。
DateTime
とはwebmeterID
同じままです。ただし、kWh
値はテーブルから更新する必要がありtemp_energydata
ます。
このためのT-SQLを正しい方法で作成するにはどうすればよいですか?
実際のSQLServerステートメントが必要であると仮定しますMERGE
。
MERGE INTO dbo.energydata WITH (HOLDLOCK) AS target
USING dbo.temp_energydata AS source
ON target.webmeterID = source.webmeterID
AND target.DateTime = source.DateTime
WHEN MATCHED THEN
UPDATE SET target.kWh = source.kWh
WHEN NOT MATCHED BY TARGET THEN
INSERT (webmeterID, DateTime, kWh)
VALUES (source.webmeterID, source.DateTime, source.kWh);
ソースにないターゲットのレコードも削除する場合:
MERGE INTO dbo.energydata WITH (HOLDLOCK) AS target
USING dbo.temp_energydata AS source
ON target.webmeterID = source.webmeterID
AND target.DateTime = source.DateTime
WHEN MATCHED THEN
UPDATE SET target.kWh = source.kWh
WHEN NOT MATCHED BY TARGET THEN
INSERT (webmeterID, DateTime, kWh)
VALUES (source.webmeterID, source.DateTime, source.kWh)
WHEN NOT MATCHED BY SOURCE THEN
DELETE;
これはもう少し人気が出てきたので、注意すべきいくつかの注意点を付けて、この回答を少し拡張する必要があると思います。
まず、古いバージョンのSQLServerのステートメントの同時実行性の問題MERGE
を報告するブログがいくつかあります。この問題が後の版で対処されたことがあるかどうかはわかりません。いずれにせよ、これは主にHOLDLOCK
またはSERIALIZABLE
ロックヒントを指定することで回避できます。
MERGE INTO dbo.energydata WITH (HOLDLOCK) AS target
[...]
より制限的なトランザクション分離レベルでも同じことを実現できます。
には、他にもいくつかの既知の問題がありMERGE
ます。(MicrosoftはConnectを無効にし、古いシステムの問題を新しいシステムの問題にリンクしなかったため、これらの古い問題を追跡するのは困難です。ありがとう、Microsoft!)私が知る限り、それらのほとんどは一般的ではありません。問題があるか、上記と同じロックのヒントで回避できますが、私はそれらをテストしていません。
現状では、私自身はステートメントに問題はありませんでしたが、今MERGE
は常にWITH (HOLDLOCK)
ヒントを使用しており、最も単純な場合にのみステートメントを使用することを好みます。
構文を覚えられないので、私はよくベーコンビットの素晴らしい答えを使いました。
ただし、通常、CTEを追加として追加して、DELETE部分をより便利にします。これは、ターゲットテーブルの一部にのみマージを適用することが非常に多いためです。
WITH target as (
SELECT * FROM dbo.energydate WHERE DateTime > GETDATE()
)
MERGE INTO target WITH (HOLDLOCK)
USING dbo.temp_energydata AS source
ON target.webmeterID = source.webmeterID
AND target.DateTime = source.DateTime
WHEN MATCHED THEN
UPDATE SET target.kWh = source.kWh
WHEN NOT MATCHED BY TARGET THEN
INSERT (webmeterID, DateTime, kWh)
VALUES (source.webmeterID, source.DateTime, source.kWh)
WHEN NOT MATCHED BY SOURCE THEN
DELETE
energydata
のデータに基づいてレコードを更新する必要がある場合は、新しいレコードが含まれていないtemp_energydata
と想定して、次のことを試してください。temp_enerydata
UPDATE e SET e.kWh = t.kWh
FROM energydata e INNER JOIN
temp_energydata t ON e.webmeterID = t.webmeterID AND
e.DateTime = t.DateTime
これがsqlfiddleの動作です
ただし、temp_energydata
新しいレコードが含まれていて、できればenergydata
1つのステートメントで挿入する必要がある場合は、BaconBitsの回答を使用する必要があります。
UPDATE ed
SET ed.kWh = ted.kWh
FROM energydata ed
INNER JOIN temp_energydata ted ON ted.webmeterID = ed.webmeterID
Update energydata set energydata.kWh = temp.kWh
where energydata.webmeterID = (select webmeterID from temp_energydata as temp)
正しい方法は次のとおりです。
UPDATE test1
INNER JOIN test2 ON (test1.id = test2.id)
SET test1.data = test2.data