I am calling an Update routine from C# and need to determine if the Update routine found a matching row to update. If it does not, I call the Insert Routine. I was hoping that if no row was updated, I would get an error which would tell me that I need to do the insert.
Is there a way to determine if a row was updated?
October 29, 2024 at 3:16 pm
What do you mean by "Update routine"? A stored procedure? A script? Or ORM or other C# code
If SQL code add something like
SELECT @@ROWCOUNT AS UpdatedCount
directly after the update.
Or you could modify the return code to return a non-zero value if @@ROWCOUNT is zero.
Why not pass your values to a stored procedure.
Then in the stored procedure you can do a proper upsert pattern
-- Inherent in the WHERE clause is the guarantee that we
-- can't update anything if the matching row isn't there.
UPDATE SchemaName.TableName
SET FieldName = PassedInValue
WHERE KeyField = PassedInKey;
IF ( @@ROWCOUNT = 0 ) -- Nothing was updated, so attempt to insert the value as a new record
BEGIN
-- Here we use the WHERE to ensure that we don't
-- insert a row if there's already a matching row.
INSERT INTO SchemaName.TableName ( SomeKey, SomeField )
SELECT SomeKeyValue, SomeValue
-- The hints are needed to ensure that two sessions
-- can't check the existance of the row at the same time
WHERE NOT EXISTS (SELECT 1 FROM SchemaName.TableName WITH (XLOCK, HOLDLOCK)
WHERE SomeKey = SomeKeyValue
);
END;
October 29, 2024 at 5:36 pm
I am using a Stored Procedure. I tried modifying it as you suggested and it updated the row and inserted the new ones correctly. Thanks for the help.
Here's the updated Stored Procedure:
CREATE PROCEDURE [dbo].[insupd_tblMRBHistory]
(@BusinessUnit char(30)
,@PartNum char(25)
,@Description varchar(50)
,@Category char(4)
,@LotNum char(25)
,@LocationID int
,@StockMRB int
,@ExtendedCost decimal(7,2)
,@TransDate datetime
,@MRBDays int
,@Closed bit)
AS
BEGIN
UPDATE [dbo].[tblMRBHistory]
SET [BusinessUnit] = @BusinessUnit,
[PartNum] = @PartNum,
[Description] = @Description,
[Category] = @Category,
[LotNum] = @LotNum,
[LocationID] = @LocationID,
[StockMRB] = @StockMRB,
[ExtendedCost] = @ExtendedCost,
[MRBDays] = @MRBDays,
[Closed] = @Closed
WHERE [PartNum] = @PartNum AND [LotNum] = @LotNum
IF (@@RWOCOUNT = 0)
INSERT INTO [dbo].[tblMRBHistory]
([BusinessUnit],
[PartNum],
[Description],
[Category],
[LotNum],
[LocationID],
[StockMRB],
[ExtendedCost],
[TransDate],
[MRBDays],
[Closed])
VALUES
(@BusinessUnit,
@PartNum,
@Description,
@Category,
@LotNum,
@LocationID,
@StockMRB,
@ExtendedCost,
@TransDate,
@MRBDays,
@Closed)
END
October 29, 2024 at 5:46 pm
If you have multiple threads, the inserting of VALUES could result in duplicates.
I would modify this to use the WHERE NOT EXISTS
IF (@@RWOCOUNT = 0)
BEGIN
INSERT INTO dbo.tblMRBHistory ( BusinessUnit, PartNum, Description, Category, LotNum, LocationID, StockMRB, ExtendedCost, TransDate, MRBDays, Closed )
SELECT @BusinessUnit, @PartNum, @Description, @Category, @LotNum, @LocationID, @StockMRB, @ExtendedCost, @TransDate, @MRBDays, @Closed
WHERE NOT EXISTS ( SELECT 1 FROM [dbo].[tblMRBHistory] WITH (XLOCK, HOLDLOCK)
WHERE [PartNum] = @PartNum AND [LotNum] = @LotNum);
END;
November 6, 2024 at 10:14 am
Michael J. Swart has a nice write-up about different kinds of upserts (and what's good and what's not):
https://michaeljswart.com/2017/07/sql-server-upsert-patterns-and-antipatterns/
Viewing 6 posts - 1 through 5 (of 5 total)
You must be logged in to reply to this topic. Login to reply
This website stores cookies on your computer.
These cookies are used to improve your website experience and provide more personalized services to you, both on this website and through other media.
To find out more about the cookies we use, see our Privacy Policy