[英]What is the best way insert/update data to the database
Given that we have the following table: 鉴于我们有下表:
CREATE TABLE TestData
(
ID INT NOT NULL PRIMARY KEY,
Value INT
)
When writing data to the table, I will try to UPDATE
the table if the ID already exists or else INSERT
a new row. 将数据写入表时,如果ID已经存在,我将尝试
UPDATE
表,否则请INSERT
新行。
There are several options that I've written or come across in production code: 我已经在生产代码中编写或遇到了几种选择:
Perform an UPDATE
query first, if no row is updated, perform an INSERT
query 首先执行
UPDATE
查询,如果没有更新行,则执行INSERT
查询
Perform an Insert
query first first, if it fails, performs an INSERT
query 首先执行
Insert
查询,如果失败,则执行INSERT
查询
Perform a SELECT
query with new ID first, then if the row exists do UPDATE
else INSERT
query 首先执行具有新ID的
SELECT
查询,然后如果该行存在,则执行UPDATE
否则INSERT
查询
Perform one big query to do all select update or insert 执行一个大查询以全部选择更新或插入
My question is what is the best practice
or most efficient
or preferred method
amongst the above options (or your own method)? 我的问题是上述选项(或您自己的方法)中的
best practice
或most efficient
或preferred method
是什么?
Example code for above options: 上述选项的示例代码:
(1) Perform an UPDATE
query first, if no row is updated, perform an INSERT
query (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) Perform an Insert
query first first, if it fails, performs an INSERT
query (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) Perform a SELECT
query with new ID first, then if the row exists do UPDATE
else INSERT
query (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) Perform one big query to do all select update or insert (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) { /*...*/ }
}
You could use MERGE . 您可以使用MERGE 。
Performs insert, update, or delete operations on a target table based on the results of a join with a source table.
根据与源表的联接结果在目标表上执行插入,更新或删除操作。
For concurrency reasons it is much better to use MERGE
than IF EXISTS/UPDATE/INSERT
and it is only one statement so less code to maintain: 由于并发原因,使用
MERGE
比使用IF EXISTS/UPDATE/INSERT
更好,并且它只是一个语句,因此维护的代码更少:
Something like: 就像是:
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;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.