Solutions for INSERT OR UPDATE on SQL Server

后端 未结 22 1868
别跟我提以往
别跟我提以往 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:51

    You can use this query. Work in all SQL Server editions. It's simple, and clear. But you need use 2 queries. You can use if you can't use MERGE

        BEGIN TRAN
    
        UPDATE table
        SET Id = @ID, Description = @Description
        WHERE Id = @Id
    
        INSERT INTO table(Id, Description)
        SELECT @Id, @Description
        WHERE NOT EXISTS (SELECT NULL FROM table WHERE Id = @Id)
    
        COMMIT TRAN
    

    NOTE: Please explain answer negatives

    0 讨论(0)
  • 2020-11-21 22:53

    I usually do what several of the other posters have said with regard to checking for it existing first and then doing whatever the correct path is. One thing you should remember when doing this is that the execution plan cached by sql could be nonoptimal for one path or the other. I believe the best way to do this is to call two different stored procedures.

    FirstSP:
    If Exists
       Call SecondSP (UpdateProc)
    Else
       Call ThirdSP (InsertProc)
    

    Now, I don't follow my own advice very often, so take it with a grain of salt.

    0 讨论(0)
  • 2020-11-21 22:54
    /*
    CREATE TABLE ApplicationsDesSocietes (
       id                   INT IDENTITY(0,1)    NOT NULL,
       applicationId        INT                  NOT NULL,
       societeId            INT                  NOT NULL,
       suppression          BIT                  NULL,
       CONSTRAINT PK_APPLICATIONSDESSOCIETES PRIMARY KEY (id)
    )
    GO
    --*/
    
    DECLARE @applicationId INT = 81, @societeId INT = 43, @suppression BIT = 0
    
    MERGE dbo.ApplicationsDesSocietes WITH (HOLDLOCK) AS target
    --set the SOURCE table one row
    USING (VALUES (@applicationId, @societeId, @suppression))
        AS source (applicationId, societeId, suppression)
        --here goes the ON join condition
        ON target.applicationId = source.applicationId and target.societeId = source.societeId
    WHEN MATCHED THEN
        UPDATE
        --place your list of SET here
        SET target.suppression = source.suppression
    WHEN NOT MATCHED THEN
        --insert a new line with the SOURCE table one row
        INSERT (applicationId, societeId, suppression)
        VALUES (source.applicationId, source.societeId, source.suppression);
    GO
    

    Replace table and field names by whatever you need. Take care of the using ON condition. Then set the appropriate value (and type) for the variables on the DECLARE line.

    Cheers.

    0 讨论(0)
  • 2020-11-21 22:54

    In SQL Server 2008 you can use the MERGE statement

    0 讨论(0)
  • 2020-11-21 22:55

    Does the race conditions really matter if you first try an update followed by an insert? Lets say you have two threads that want to set a value for key key:

    Thread 1: value = 1
    Thread 2: value = 2

    Example race condition scenario

    1. key is not defined
    2. Thread 1 fails with update
    3. Thread 2 fails with update
    4. Exactly one of thread 1 or thread 2 succeeds with insert. E.g. thread 1
    5. The other thread fails with insert (with error duplicate key) - thread 2.

      • Result: The "first" of the two treads to insert, decides value.
      • Wanted result: The last of the 2 threads to write data (update or insert) should decide value

    But; in a multithreaded environment, the OS scheduler decides on the order of the thread execution - in the above scenario, where we have this race condition, it was the OS that decided on the sequence of execution. Ie: It is wrong to say that "thread 1" or "thread 2" was "first" from a system viewpoint.

    When the time of execution is so close for thread 1 and thread 2, the outcome of the race condition doesn't matter. The only requirement should be that one of the threads should define the resulting value.

    For the implementation: If update followed by insert results in error "duplicate key", this should be treated as success.

    Also, one should of course never assume that value in the database is the same as the value you wrote last.

    0 讨论(0)
  • 2020-11-21 22:56

    See my detailed answer to a very similar previous question

    @Beau Crawford's is a good way in SQL 2005 and below, though if you're granting rep it should go to the first guy to SO it. The only problem is that for inserts it's still two IO operations.

    MS Sql2008 introduces merge from the SQL:2003 standard:

    merge tablename with(HOLDLOCK) as target
    using (values ('new value', 'different value'))
        as source (field1, field2)
        on target.idfield = 7
    when matched then
        update
        set field1 = source.field1,
            field2 = source.field2,
            ...
    when not matched then
        insert ( idfield, field1, field2, ... )
        values ( 7,  source.field1, source.field2, ... )
    

    Now it's really just one IO operation, but awful code :-(

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