我有一个名为energydata
它只有三列
(webmeterID, DateTime, kWh)
我在表temp_energydata
中有一组新的更新数据。
DateTime
和webmeterID
保持不变。但kWh
值需要从temp_energydata
表更新。
如何以正确的方式编写T-SQL?
答案 0 :(得分:114)
假设您想要一个实际的SQL Server 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;
因为这已经变得更受欢迎,我觉得我应该稍微扩展这个答案,并注意一些注意事项。
首先,有几个博客在旧版本的SQL Server中报告concurrency issues with the MERGE
statement。我不知道这个问题是否曾在以后的版本中得到解决。无论哪种方式,通过指定HOLDLOCK
或SERIALIZABLE
锁定提示,可以在很大程度上解决这个问题:
MERGE INTO dbo.energydata WITH (HOLDLOCK) AS target
[...]
您还可以使用更具限制性的事务隔离级别来完成相同的操作。
several other known issues有MERGE
。 (请注意,由于微软认为Connect并没有将旧系统中的问题与新系统中的问题联系起来,因此很难追查这些旧问题。谢谢,微软!)据我所知,其中大多数都不常见问题或可以使用与上面相同的锁定提示解决,但我没有测试它们。
实际上,即使我自己从未对MERGE
语句有任何问题,我现在总是使用WITH (HOLDLOCK)
提示,而我更喜欢只使用最直接的语句案件。
答案 1 :(得分:13)
我经常使用培根比特很好的答案,因为我无法记住语法。
但是我通常添加一个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
答案 2 :(得分:5)
如果您需要根据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
,最好只有一个陈述,那么您一定应该接受培根比特给出的答案。
答案 3 :(得分:0)
UPDATE ed
SET ed.kWh = ted.kWh
FROM energydata ed
INNER JOIN temp_energydata ted ON ted.webmeterID = ed.webmeterID
答案 4 :(得分:0)
Update energydata set energydata.kWh = temp.kWh
where energydata.webmeterID = (select webmeterID from temp_energydata as temp)
答案 5 :(得分:-7)
正确的方法是:
UPDATE test1
INNER JOIN test2 ON (test1.id = test2.id)
SET test1.data = test2.data