sql-server

How does sql server choose values in an update statement where there are multiple options?


I have an update statement in SQL server where there are four possible values that can be assigned based on the join. It appears that SQL has an algorithm for choosing one value over another, and I'm not sure how that algorithm works.

As an example, say there is a table called Source with two columns (Match and Data) structured as below: (The match column contains only 1's, the Data column increments by 1 for every row)

Match Data
1 1
1 2
1 3
1 4

That table will update another table called Destination with the same two columns structured as below:

Match Data
1 NULL

If you want to update the ID field in Destination in the following way:

UPDATE   
  Destination  
 SET  
   Data = Source.Data 
FROM  
Destination  
INNER JOIN  
Source  
ON  
Destination.Match = Source.Match

there will be four possible options that Destination.ID will be set to after this query is run. I've found that messing with the indexes of Source will have an impact on what Destination is set to, and it appears that SQL Server just updates the Destination table with the first value it finds that matches.

Is that accurate? Is it possible that SQL Server is updating the Destination with every possible value sequentially and I end up with the same kind of result as if it were updating with the first value it finds? It seems to be possibly problematic that it will seemingly randomly choose one row to update, as opposed to throwing an error when presented with this situation.

Thank you.

P.S. I apologize for the poor formatting. Hopefully, the intent is clear.


Solution

  • It sets all of the results to the Data. Which one you end up with after the query depends on the order of the results returned (which one it sets last).

    Since there's no ORDER BY clause, you're left with whatever order Sql Server comes up with. That will normally follow the physical order of the records on disk, and that in turn typically follows the clustered index for a table. But this order isn't set in stone, particularly when joins are involved. If a join matches on a column with an index other than the clustered index, it may well order the results based on that index instead. In the end, unless you give it an ORDER BY clause, Sql Server will return the results in whatever order it thinks it can do fastest.

    You can play with this by turning your upate query into a select query, so you can see the results. Notice which record comes first and which record comes last in the source table for each record of the destination table. Compare that with the results of your update query. Then play with your indexes again and check the results once more to see what you get.

    Of course, it can be tricky here because UPDATE statements are not allowed to use an ORDER BY clause, so regardless of what you find, you should really write the join so it matches the destination table 1:1. You may find the APPLY operator useful in achieving this goal, and you can use it to effectively JOIN to another table and guarantee the join only matches one record.