简体   繁体   中英

SQL Server : update value if it does not exist in a column

I am using SQL Server 2008 and trying to create a statement which will update a single value within a row from another table if a certain parameter is met. I need to make this as simple as possible for a member of my team to use.

So in this case I want to store 2 values, the Sales Order and the reference. Unfortunately the Sales order has a unique identifier that I need to record and enter into the jobs table and NOT the actual sales order reference.

The parameter which needs to be met is that the Sales order unique identifier cannot exist anywhere in the sales order column within the jobs table. I can get this to work when the while value is set to 1 but not when it's set to 0 and in my head it should be set to 0. Anyone got any ideas why this doesn't work?

/****** Attach an SO to a WO  ******/

/****** ONLY EDIT THE VALUES BETWEEN '' ******/
Declare @Reference nvarchar(30);
Set @Reference = 'WO16119';

Declare @SO nvarchar(30);
Set @SO = '0000016205';

/****** DO NOT ALTER THE CODE BEYOND THIS POINT!!!!!!!!!!!!! ******/

/* store more values */
Declare @SOID nvarchar(30);
Set @SOID = (Select SOPOrderReturnID
        FROM Test_DB.dbo.SOTable
        Where DocumentNo = @SO);

/*  check if update should run */                           
Declare @Check nvarchar (30);
Set @Check = (Select case when exists   (select * 
                                from Test_DB.dbo.Jobs 
                                where SalesOrderNumber != @SOID)
                                then CAST(1 AS BIT)
                                ELSE CAST(0 AS BIT) End)
While (@Check = 0)

/* if check is true run code below */
Begin
Update Test_DB.dbo.jobs
SET SalesOrderNumber = (Select SOPOrderReturnID
                    FROM Test_DB.dbo.SOPOrderReturn
                    Where DocumentNo = @SO)
Where Reference = @Reference
END;

A few comments. First in order to avoid getting into a never ending loop you may want to change your while for an IF statement. You aren't changing the @check value so that will run forever:

IF (@Check = 0)
BEGIN
   /* if check is true run code below */
   Update Test_DB.dbo.jobs
   SET SalesOrderNumber = (Select SOPOrderReturnID
                FROM Test_DB.dbo.SOPOrderReturn
                Where DocumentNo = @SO)
   Where Reference = @Reference
END

Then, without knowing your application I would say that the way you make checks is going to require you to lock your tables to avoid other users invalidating the results of your SELECTs.

I would go instead to creating a UNIQUE constraint over the column you want to be unique and handle the error gracefully. This way you don't need to create big locks on your tables

CREATE UNIQUE INDEX IX_UniqueIndex ON Test_DB.dbo.Jobs(SalesOrderNumber)

As per your comment if you cannot create a unique index you may want to try the following SQL although it could cause too much locking and be affected by race conditions:

IF NOT EXISTS (SELECT 1 FROM Test_DB.dbo.Jobs j INNER JOIN Test_DB.dbo.SOTable so ON j.SalesOrderNumber = so.SPOrderReturnId)
BEGIN
    UPDATE Test_DB.dbo.jobs
    SET SalesOrderNumber =  so.SOPOrderReturnID
    FROM
        Test_DB.dbo.Jobs j 
        INNER JOIN Test_DB.dbo.SOTable so ON j.SalesOrderNumber = so.SPOrderReturnId
    Where 
        Reference = @Reference
END

The risk of this are that you are running to separate queries (the select and the update) so between them the state of the database could change. So it may be possible that the first query returns nothing exists for that Id but at the moment of the update other user has inserted/updated that data so the previous result is no longer true.

You can try to avoid this problem by using a isolation level that locks the table on the read (like Serializable) but that could cause locks and even deadlocks in the database.

The best solution here is the unique index. If a certain column has to be unique inside a table the best controller system is the db itself by defining constraints.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM