SQL Server 是不是提供类似于 MySQL 的 ON DUPLICATE KEY UPDATE 的功能
Posted
技术标签:
【中文标题】SQL Server 是不是提供类似于 MySQL 的 ON DUPLICATE KEY UPDATE 的功能【英文标题】:Does SQL Server Offer Anything Like MySQL's ON DUPLICATE KEY UPDATESQL Server 是否提供类似于 MySQL 的 ON DUPLICATE KEY UPDATE 的功能 【发布时间】:2010-11-14 22:14:06 【问题描述】:在 mysql 中,如果您指定 ON DUPLICATE KEY UPDATE 并且插入的行会导致 UNIQUE 索引或 PRIMARY KEY 中的重复值,则会执行旧行的更新。例如,如果列 a 被声明为 UNIQUE 并且包含值 1,则以下两个语句具有相同的效果:
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
UPDATE table SET c=c+1 WHERE a=1;
我不相信我在 T-SQL 中遇到过类似的东西。 SQL Server 是否提供与 MySQL 的 ON DUPLICATE KEY UPDATE 相当的功能?
【问题讨论】:
可以用存储过程来模拟。我不知道确切的代码。 @Robert Harvey - 我总是通过检查行是否存在来执行操作。如果是,则执行更新,否则插入新行。你也是这么想的吗? 【参考方案1】:没有等效的 DUPLICATE KEY UPDATE,但 MERGE 和 WHEN MATCHED 可能对您有用
Inserting, Updating, and Deleting Data by Using MERGE
【讨论】:
请注意,MERGE 不能免于高并发插入冲突。您必须使用 WITH (UPDLOCK, HOLDLOCK) 进行合并,以免发生冲突。一些超高每秒事务的系统使用不同的策略,不使用锁,但任何错误都会被捕获,然后转换为更新。【参考方案2】:令我惊讶的是,此页面上的答案都没有包含实际查询的示例,所以你去吧:
一个更复杂的插入数据然后处理重复的例子
MERGE
INTO MyBigDB.dbo.METER_DATA WITH (HOLDLOCK) AS target
USING (SELECT
77748 AS rtu_id
,'12B096876' AS meter_id
,56112 AS meter_reading
,'20150602 00:20:11' AS local_time) AS source
(rtu_id, meter_id, meter_reading, time_local)
ON (target.rtu_id = source.rtu_id
AND target.time_local = source.time_local)
WHEN MATCHED
THEN UPDATE
SET meter_id = '12B096876'
,meter_reading = 56112
WHEN NOT MATCHED
THEN INSERT (rtu_id, meter_id, meter_reading, time_local)
VALUES (77748, '12B096876', 56112, '20150602 00:20:11');
【讨论】:
您先生...是救生员。我真的很讨厌微软的文档......他们总是给出除了最常用的例子之外的所有例子'MERGE INTO MyFancyTableName WITH (HOLDLOCK) AS target USING (SELECT :id AS id, :lastaccess AS lastaccess ) AS source (id,lastaccess) ON (target.id = source.id) WHEN MATCHED THEN UPDATE SET lastaccess = :lastaccess2 WHEN NOT MATCHED THEN INSERT (id, lastaccess) VALUES (:id2, :lastaccess3);'
我是否需要在USING
选择中发布这两个变量,还是只需要id
就足够了吗?
感谢您对 Merge 命令的引用。我应该指出,在 MATCHED STATEMENTS 中,您使用的值与您定义为源的值相同。因此,如果您希望更新大量记录,您应该像这样分配源值:
WHEN MATCHED THEN UPDATE SET METER_ID = source.RTU_ID, METER_READING = source.METER_ID
。对不起,双重评论,*** 没有让我编辑过去 6 分钟。
我尝试使用 MERGE INTO,但得到一个错误,它不能用于内存优化表。默认情况下,使用 CREATE TABLE 语句创建的表是内存优化表。我不知道使用 WITH (HOLDLOCK) 是否可行。会试一试。顺便说一句..您代码中的表 - MyBigDB.dbo.METER_DATA 是内存优化的吗?要查找表是否内存优化,请参考 - ***.com/questions/58866622/…【参考方案3】:
您可以尝试相反的方法。它或多或少都在做同样的事情。
UPDATE tablename
SET field1 = 'Test1',
field2 = 'Test2'
WHERE id = 1
IF @@ROWCOUNT = 0
INSERT INTO tablename
(id,
field1,
field2)
VALUES (1,
'Test1',
'Test2')
【讨论】:
【参考方案4】:SQL Server 2008 具有此功能,作为 TSQL 的一部分。 在此处查看有关 MERGE 语句的文档 - http://msdn.microsoft.com/en-us/library/bb510625.aspx
【讨论】:
请注意,MERGE 不能免于高并发插入冲突。您必须使用 WITH (UPDLOCK, HOLDLOCK) 合并才能不发生冲突。一些超高每秒事务的系统使用不同的策略,不使用锁,但任何错误都会被捕获,然后转换为更新。【参考方案5】:SQL server 2000 及更高版本有一个代替触发器的概念,它可以完成想要的功能——尽管在幕后会有一个讨厌的触发器。
检查“插入还是更新?”部分
http://msdn.microsoft.com/en-us/library/aa224818(SQL.80).aspx
【讨论】:
以上是关于SQL Server 是不是提供类似于 MySQL 的 ON DUPLICATE KEY UPDATE 的功能的主要内容,如果未能解决你的问题,请参考以下文章
如何在 MySQL 中打破类似于 MS SQL Server 的列名?
SQL Server 2008 中的功能类似于 mysql 中的 GREATEST?
Sql server中有没有replace语句? 没有的话,怎样实现类似于mySql中的repla
SQL Server 上是不是有类似于 Oracle 的 PIPE ROW 的代码?