鉴于我们有以下表格:
CREATE TABLE TestData
(
ID INT NOT NULL PRIMARY KEY,
Value INT
)
在向表中写入数据时,如果ID已存在,我将尝试UPDATE
表,或者INSERT
新行。
我在生产代码中编写或遇到过几个选项:
首先执行UPDATE
查询,如果没有更新行,请执行INSERT
查询
首先执行Insert
查询,如果失败,请执行INSERT
查询
首先使用新ID执行SELECT
查询,如果该行存在,请执行UPDATE
其他INSERT
查询
执行一个大查询以执行所有选择更新或插入
我的问题是上述选项(或您自己的方法)中的best practice
或most efficient
或preferred method
是什么?
以上选项的示例代码:
(1)首先执行UPDATE
查询,如果没有更新行,请执行INSERT
查询
int affectedRows = 0;
using (IDbCommand updateCmd = new SqlCommand("UPDATE TestData SET Value = @Value WHERE ID = @ID", myConn))
{
try
{
// ...add params
affectedRows = updateCmd.ExecuteNonQuery();
}
catch (SqlException) { /*...*/ }
}
if (affectedRows == 0)
{
using (IDbCommand insertCmd = new SqlCommand("INSERT INTO TestData VALUES (@ID, @Value)", myConn))
{
try
{
// ...add params
affectedRows = insertCmd.ExecuteNonQuery();
}
catch (SqlException) { /*...*/ }
}
}
(2)首先执行Insert
查询,如果失败,则执行INSERT
查询
int affectedRows = 0;
using (IDbCommand insertCmd = new SqlCommand("INSERT INTO TestData VALUES (@ID, @Value)", myConn))
{
try
{
// ... add params
affectedRows = insertCmd.ExecuteNonQuery();
}
catch (SqlException) { /*...*/ }
}
if (affectedRows == 0)
{
using (IDbCommand updateCmd = new SqlCommand("UPDATE TestData SET Value = @Value WHERE ID = @ID", myConn))
{
try
{
// ...add params
affectedRows = updateCmd.ExecuteNonQuery();
}
catch (SqlException) { /*...*/ }
}
}
(3)首先使用新ID执行SELECT
查询,如果该行存在,请执行UPDATE
其他INSERT
查询
bool dataExist = false;
// ...
using (IDbCommand selectCmd = new SqlCommand("SELECT ID FROM TestDate WHERE ID=@ID", myConn))
{
try
{
// ... add param
using (IDataReader reader = selectCmd.ExecuteReader())
dataExist = reader.Read();
}
catch (SqlException) { /*...*/ }
}
if (dataExist) { /* update query, similar to above one*/ }
else { /* insert, similar to above one */ }
(4)执行一个大查询以执行所有选择更新或插入
string query = "IF EXISTS (SELECT ID FROM TestData WHERE ID=@ID) " +
"UPDATE TestData SET Value = @Value WHERE ID = @ID " +
"ELSE INSERT INTO TestData VALUES (@ID, @Value)";
using (IDbCommand bigQueryCmd = new SqlCommand(query, myConn))
{
try
{
// ... add param
bigQueryCmd.ExecuteNonQuery();
}
catch (SqlException) { /*...*/ }
}
答案 0 :(得分:0)
您可以使用 MERGE 。
基于目标表执行插入,更新或删除操作 关于与源表的连接结果。
出于并发原因,使用 MERGE
比IF EXISTS/UPDATE/INSERT
要好得多,而且只有一个语句,因此维护的代码更少:
类似的东西:
<强> SqlFiddleDemo 强>
CREATE TABLE TestData (
ID INT NOT NULL PRIMARY KEY,
Value INT);
INSERT INTO TestData
VALUES (1,3);
DECLARE @id INT = 1, @value INT = 10; -- will update
--DECLARE @id INT = 2, @value INT = 10; -- will insert
;MERGE TestData AS TGT
USING (SELECT * FROM (SELECT @id AS ID, @value AS VALUE) AS t) AS SRC
ON TGT.ID = SRC.ID
WHEN MATCHED THEN
UPDATE SET Value = SRC.[VALUE]
WHEN NOT MATCHED THEN
INSERT (ID, [VALUE])
VALUES (SRC.ID, SRC.[VALUE]);
SELECT *
FROM TestData;