Solutions for INSERT OR UPDATE on SQL Server

后端 未结 22 1869
别跟我提以往
别跟我提以往 2020-11-21 22:23

Assume a table structure of MyTable(KEY, datafield1, datafield2...).

Often I want to either update an existing record, or insert a new record if it does

相关标签:
22条回答
  • 2020-11-21 22:58

    I had tried below solution and it works for me, when concurrent request for insert statement occurs.

    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
    
    0 讨论(0)
  • 2020-11-21 22:59

    That depends on the usage pattern. One has to look at the usage big picture without getting lost in the details. For example, if the usage pattern is 99% updates after the record has been created, then the 'UPSERT' is the best solution.

    After the first insert (hit), it will be all single statement updates, no ifs or buts. The 'where' condition on the insert is necessary otherwise it will insert duplicates, and you don't want to deal with locking.

    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
    
    0 讨论(0)
  • 2020-11-21 23:00

    Do an UPSERT:

    UPDATE MyTable SET FieldA=@FieldA WHERE Key=@Key
    
    IF @@ROWCOUNT = 0
       INSERT INTO MyTable (FieldA) VALUES (@FieldA)
    

    http://en.wikipedia.org/wiki/Upsert

    0 讨论(0)
  • 2020-11-21 23:00

    Assuming that you want to insert/update single row, most optimal approach is to use SQL Server's REPEATABLE READ transaction isolation level:

    SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
    BEGIN TRANSACTION
    
        IF (EXISTS (SELECT * FROM myTable WHERE key=@key)
            UPDATE myTable SET ...
            WHERE key=@key
        ELSE
            INSERT INTO myTable (key, ...)
            VALUES (@key, ...)
    
    COMMIT TRANSACTION
    

    This isolation level will prevent/block subsequent repeatable read transactions from accessing same row (WHERE key=@key) while currently running transaction is open. On the other hand, operations on another row won't be blocked (WHERE key=@key2).

    0 讨论(0)
  • 2020-11-21 23:01

    MS SQL Server 2008 introduces the MERGE statement, which I believe is part of the SQL:2003 standard. As many have shown it is not a big deal to handle one row cases, but when dealing with large datasets, one needs a cursor, with all the performance problems that come along. The MERGE statement will be much welcomed addition when dealing with large datasets.

    0 讨论(0)
  • 2020-11-21 23:01

    If you use ADO.NET, the DataAdapter handles this.

    If you want to handle it yourself, this is the way:

    Make sure there is a primary key constraint on your key column.

    Then you:

    1. Do the update
    2. If the update fails because a record with the key already exists, do the insert. If the update does not fail, you are finished.

    You can also do it the other way round, i.e. do the insert first, and do the update if the insert fails. Normally the first way is better, because updates are done more often than inserts.

    0 讨论(0)
提交回复
热议问题