SQL SERVER – How to Update Two Tables in One Statement?

One Statement normally updates one target table in SQL Server. I use a transaction when two changes must succeed together.

Two separate folio covers are held beneath one shared press restraint.

Joining tables in UPDATE does not make every joined table an update target. Triggers can cause additional side effects, but that is different from naming two target tables in one ordinary UPDATE.

SET XACT_ABORT ON;
CREATE TABLE #Table1 (ID int PRIMARY KEY, Col1 varchar(20));
CREATE TABLE #Table2 (ID int PRIMARY KEY, Col2 varchar(20));
INSERT #Table1 VALUES (1, 'Before');
INSERT #Table2 VALUES (1, 'Before');
BEGIN TRY
    BEGIN TRANSACTION;
    UPDATE #Table1 SET Col1 = 'After' WHERE ID = 1;
    UPDATE #Table2 SET Col2 = 'After' WHERE ID = 1;
    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    IF XACT_STATE() <> 0 ROLLBACK TRANSACTION;
    THROW;
END CATCH;
SELECT * FROM #Table1;
SELECT * FROM #Table2;
DROP TABLE #Table1, #Table2;
Both temporary tables contain After following two UPDATE statements in one successful transaction.
Both temporary tables contain After following two UPDATE statements in one successful transaction.

This temporary-table example uses two UPDATE statements in one transaction. TRY/CATCH rolls back an outstanding transaction and rethrows the error. XACT_ABORT handles many runtime errors by aborting the transaction. BEGIN followed by COMMIT alone doesn’t handle every failure.

I choose specific predicates and keep application transactions short. A zero-row update isn’t automatically an error. If exactly one row is required, check @@ROWCOUNT immediately after each update. Raise an error when that business rule fails.

Reference: XACT_ABORT and transaction error handling.

One transaction is not one UPDATE target, it is a boundary around the changes that must succeed together.

Published by Pinal Dave on SQLAuthority. More of my work at pinaldave.com.


Discover more from SQL Authority with Pinal Dave

Subscribe to get the latest posts sent to your email.

SQL Scripts, SQL Server, SQL Transactions
Previous Post
SQL SERVER – sp_server_diagnostics – The User Does Not Have Permission to Perform this Action. (297)
Next Post
Measure Page Splits in SQL Server With T-SQL

Related Posts

16 Comments. Leave new

  • Adam Cruickshank
    June 7, 2017 1:02 am

    I’m stunned that this needs discussing in 2017.
    There’s probably an article from 20 years covering this.
    Anybody asking such a question needs to read a manual and feel lucky they exist.
    I used to learn without manuals and before Google was invented.

    Reply
    • Adam, I agree with you but trust me the question which still get asked are surprising.

      Reply
    • Adam, regarding your statement ‘read a manual and feel lucky they exist’; so, you came right out of the womb knowing everything, or perhaps you learn by osmosis? Amazing. That would lead one to wonder why you are reading this in the first place. Furthermore, who made you the judge as to the value of the existence of another? Go read some manuals or Google how not to be so judgemental and miserable.

      Reply
    • Fact is, as time progresses, technological advancements are made.
      Are you still coding with the same techniques/restrictions you had 20 years ago? If you are, then that would be something to be stunned at.

      Reply
  • Of course you are right, but I think this is due to the fact that most of the IT professionals are not focused only to a single technology like SQL but are full stack.
    In my (well, by now, short) experience, I had to learn both client side and server side technology, all on demand. If a frontend developer needs to create (or modify) a functionality in SQL, he has no time to read manuals, but only to have a glimpse on the topics related to the new functionality.

    Reply
  • Can’t we update using join?

    Reply
    • You can use update with join, but you can only update one of the joint tables.
      Update a
      set a.value1 = b.value2
      from a join b on…

      but not (or similar):
      Update a, b
      set a.value1 = b.value2, b.value5 = ‘x’
      from a join b on…

      Reply
  • Alexandr Pechenko
    January 2, 2018 8:43 pm

    you can use view with INSTEAD OF trigger:

    CREATE TABLE [dbo].[t1]( [id] [uniqueidentifier] NOT NULL, [FirstName] [varchar](50) NULL)
    go
    CREATE TABLE [dbo].[t2]( [id] [uniqueidentifier] NOT NULL, [LastName] [varchar](50) NULL)
    GO

    insert into t1
    values(’76CC1607-1DAE-4878-A549-26518696CEF8′,’Alexandr’)

    insert into t2
    values(’76CC1607-1DAE-4878-A549-26518696CEF8′,’Pechenko’)

    go

    create VIEW dbo.v1 with schemabinding
    as
    select dbo.t1.id, dbo.t1.FirstName, dbo.t2.LastName
    from dbo.t1
    join dbo.t2 on dbo.t2.id = dbo.t1.id

    go

    CREATE TRIGGER tr_v1_upd
    ON dbo.v1
    INSTEAD OF UPDATE
    AS

    UPDATE s
    SET s.FirstName = i.FirstName
    FROM dbo.t1 s
    JOIN inserted i
    ON s.id = i.id;

    UPDATE s
    SET s.LastName = i.LastName
    FROM dbo.t2 s
    JOIN inserted i
    ON s.id = i.id;

    go

    update dbo.v1 set
    FirstName = ‘FN’,
    LastName = ‘LN’
    where id = ’76CC1607-1DAE-4878-A549-26518696CEF8′

    go

    select * from v1

    Reply
  • Hi Pinal,

    It might be workaround, but why we do need to complicate it by creating view and trigger to achieve this? The same can be achieved using transactions easily.

    Thanks,
    Srinivas

    Reply
    • You are absolutely right. Sometimes things are not as simple as they sound in implementation. Will you be able to ask question to your manager if he says – “If SQL have some way, do it”

      Reply
  • Hi Pinal,

    Yeah, I agree sometimes we don’t have choices.

    Thanks,
    Srini

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.