简体   繁体   English

什么是插入/更新数据到数据库的最佳方法

[英]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: 我已经在生产代码中编写或遇到了几种选择:

  1. Perform an UPDATE query first, if no row is updated, perform an INSERT query 首先执行UPDATE查询,如果没有更新行,则执行INSERT查询

  2. Perform an Insert query first first, if it fails, performs an INSERT query 首先执行Insert查询,如果失败,则执行INSERT查询

  3. Perform a SELECT query with new ID first, then if the row exists do UPDATE else INSERT query 首先执行具有新ID的SELECT查询,然后如果该行存在,则执行UPDATE否则INSERT查询

  4. 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 practicemost efficientpreferred 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: 就像是:

SqlFiddleDemo 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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 快速插入SQL数据和相关行的最佳方法是什么? - What is the best way to fast insert SQL data and dependant rows? 定期自动更新每条记录数据的最佳方法是什么 - What's the best way to auto update per record data periodically 将图像和数字数据一次添加到数据库的最佳方法是什么? - What is the best way to add image and numerical data to the database at once? 从数据库将数据加载到以下结构的最佳方法是什么? - What is the best way to load data to the following structure from database? 从数据库中的数据生成XML的最佳方法是什么? - What is the best way to generate XML from the data in the database? 通过MVC将数据写入数据库的最佳方法是什么? - What is the best way to write data via MVC into database? 根据单元格选择从数据库中收集数据的最佳方法是什么 - What is the best way to gather data from database based on the cell selections 更新实体的最佳方法是什么? - What is best way to update entity? 更新datagridview的最佳方法是什么? - What is the best way to update datagridview? WPF-将数据从数据库绑定到复选框控件的最佳方法是什么 - WPF - what is the best way to bind data from a database to a checkbox control
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM