use*_*767 59 t-sql sql-server-2008
我有一个名为数据的表 energydata
它只有三列
(webmeterID, DateTime, kWh)
Run Code Online (Sandbox Code Playgroud)
我在表中有一组新的更新数据temp_energydata.
在DateTime和webmeterID保持不变.但是kWh值需要从temp_energydata表中更新.
如何以正确的方式编写T-SQL?
Bac*_*its 117
假设您需要一个实际的SQL ServerMERGE语句:
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);
Run Code Online (Sandbox Code Playgroud)
如果您还想删除目标中不在源中的记录:
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;
Run Code Online (Sandbox Code Playgroud)
因为这已经变得更受欢迎,我觉得我应该稍微扩展这个答案,并注意一些注意事项.
首先,有几个博客报告旧版SQL Server中的MERGE语句的并发性问题.我不知道这个问题是否曾在以后的版本中得到解决.无论哪种方式,这可以在很大程度上通过指定HOLDLOCK或SERIALIZABLE锁定提示来解决:
MERGE INTO dbo.energydata WITH (HOLDLOCK) AS target
[...]
Run Code Online (Sandbox Code Playgroud)
您还可以使用更具限制性的事务隔离级别来完成相同的操作.
还有其他一些已知问题与MERGE.(请注意,由于微软认为Connect并没有将旧系统中的问题与新系统中的问题联系起来,因此很难追查这些旧问题.谢谢,微软!)据我所知,其中大多数都不常见问题或可以解决与上面相同的锁定提示,但我没有测试它们.
事实上,尽管我自己从来没有遇到任何问题,但MERGE我现在总是使用WITH (HOLDLOCK)提示,而我更喜欢只在最直接的情况下使用该语句.
Pat*_*erg 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
Run Code Online (Sandbox Code Playgroud)
如果您只需要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
Run Code Online (Sandbox Code Playgroud)
这是工作的sqlfiddle
但是,如果temp_energydata包含新记录,并且您energydata最好将其插入到一条语句中,那么您绝对应该使用培根比特斯给出的答案。