假设MyTable的表结构(KEY, datafield1, datafield2…)
通常,我希望更新现有记录,或者插入不存在的新记录。
从本质上讲:
IF (key exists)
run update command
ELSE
run insert command
最好的写法是什么?
假设MyTable的表结构(KEY, datafield1, datafield2…)
通常,我希望更新现有记录,或者插入不存在的新记录。
从本质上讲:
IF (key exists)
run update command
ELSE
run insert command
最好的写法是什么?
当前回答
如果执行UPDATE If -no-rows-updated then INSERT路由,考虑先执行INSERT以防止竞争条件(假设没有插入DELETE)
INSERT INTO MyTable (Key, FieldA)
SELECT @Key, @FieldA
WHERE NOT EXISTS
(
SELECT *
FROM MyTable
WHERE Key = @Key
)
IF @@ROWCOUNT = 0
BEGIN
UPDATE MyTable
SET FieldA=@FieldA
WHERE Key=@Key
IF @@ROWCOUNT = 0
... record was deleted, consider looping to re-run the INSERT, or RAISERROR ...
END
除了避免竞争条件之外,如果在大多数情况下记录已经存在,那么这将导致INSERT失败,浪费CPU。
在SQL2008以后使用MERGE可能更可取。
其他回答
这取决于使用模式。一个人必须在不迷失在细节的情况下看到使用的大局观。例如,如果使用模式是在创建记录后99%更新,那么'UPSERT'是最佳解决方案。
在第一次插入(hit)之后,它将全部是单个语句更新,没有if或but。插入的'where'条件是必要的,否则它将插入重复的数据,并且您不希望处理锁定。
UPDATE <tableName> SET <field>=@field WHERE key=@key;
IF @@ROWCOUNT = 0
BEGIN
INSERT INTO <tableName> (field)
SELECT @field
WHERE NOT EXISTS (select * from tableName where key = @key);
END
我尝试了下面的解决方案,它为我工作,当插入语句发生并发请求时。
begin tran
if exists (select * from table with (updlock,serializable) where key = @key)
begin
update table set ...
where key = @key
end
else
begin
insert table (key, ...)
values (@key, ...)
end
commit tran
如果你想一次UPSERT多个记录,你可以使用ANSI SQL:2003 DML语句MERGE。
MERGE INTO table_name WITH (HOLDLOCK) USING table_name ON (condition)
WHEN MATCHED THEN UPDATE SET column1 = value1 [, column2 = value2 ...]
WHEN NOT MATCHED THEN INSERT (column1 [, column2 ...]) VALUES (value1 [, value2 ...])
查看在SQL Server 2005中模拟MERGE语句。
如果你使用ADO。NET, DataAdapter处理这个。
如果你想自己处理,方法如下:
确保在键列上有一个主键约束。
然后你:
进行更新 如果更新失败是因为已经存在具有键的记录,则执行插入操作。如果更新没有失败,您就完成了。
你也可以反过来做,即先做插入,然后在插入失败时进行更新。通常第一种方法更好,因为更新比插入更频繁。
如果执行UPDATE If -no-rows-updated then INSERT路由,考虑先执行INSERT以防止竞争条件(假设没有插入DELETE)
INSERT INTO MyTable (Key, FieldA)
SELECT @Key, @FieldA
WHERE NOT EXISTS
(
SELECT *
FROM MyTable
WHERE Key = @Key
)
IF @@ROWCOUNT = 0
BEGIN
UPDATE MyTable
SET FieldA=@FieldA
WHERE Key=@Key
IF @@ROWCOUNT = 0
... record was deleted, consider looping to re-run the INSERT, or RAISERROR ...
END
除了避免竞争条件之外,如果在大多数情况下记录已经存在,那么这将导致INSERT失败,浪费CPU。
在SQL2008以后使用MERGE可能更可取。