Let's say you're running an UPDATE statement on a table, but the information you're putting into this base table is from some other auxiliary table. Normally, you would JOIN the data and not expect the rows in the UPDATE statement's FROM clause to multiply, maintaining that one new row maps to one old row in the base table.
But I was wondering what would happen if your JOIN table was ambiguous somehow, like you couldn't account for each base entity mapping only to one joined entity. Or if you did something nonsensical like join to a base table to a table of its children and updated the base table using that information. How would it choose? Now there are multiple rows per one base table row.
I ran a statement like this in SQL Server 2005 and it seemed to be choosing the first row in each set. But that just seems wrong to me. Shouldn't it fire an error? Why is this desired behavior?
Example code
-- normal
-- categories are one-to-many bundles
update bundles_denormalized set category = c.description
from bundles_denormalized b
left join categories c
on b.category_id = c.id
-- ambiguous
-- bundles are one-to-many products
update bundles_denormalized set category = p.description
from bundles_denormalized b
left join products p
on b.id = p.bundle_id
From BOL on UPDATE
Using UPDATE with the FROM Clause
The results of an UPDATE statement are undefined if the statement includes a FROM clause that is not specified in such a way that only one value is available for each column occurrence that is updated, that is if the UPDATE statement is not deterministic. For example, in the UPDATE statement in the following script, both rows in Table1 meet the qualifications of the FROM clause in the UPDATE statement; but it is undefined which row from Table1 is used to update the row in Table2.
USE AdventureWorks; GO IF OBJECT_ID ('dbo.Table1', 'U') IS NOT NULL DROP TABLE dbo.Table1; GO IF OBJECT_ID ('dbo.Table2', 'U') IS NOT NULL DROP TABLE dbo.Table2; GO CREATE TABLE dbo.Table1 (ColA int NOT NULL, ColB decimal(10,3) NOT NULL); GO CREATE TABLE dbo.Table2 (ColA int PRIMARY KEY NOT NULL, ColB decimal(10,3) NOT NULL); GO INSERT INTO dbo.Table1 VALUES(1, 10.0); INSERT INTO dbo.Table1 VALUES(1, 20.0); INSERT INTO dbo.Table2 VALUES(1, 0.0); GO UPDATE dbo.Table2 SET dbo.Table2.ColB = dbo.Table2.ColB + dbo.Table1.ColB FROM dbo.Table2 INNER JOIN dbo.Table1 ON (dbo.Table2.ColA = dbo.Table1.ColA); GO SELECT ColA, ColB FROM dbo.Table2;
In other words, it is a valid syntax and it is not going to throw an error or exception.
But at the same time you cannot be sure that the update value will be the first or the last record from your FROM clause as it is not defined.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With