SQL Server - Update SQL help

Asked By David C
12-Jul-07 06:12 PM
I have the following SQL that is not working and I need help with it.

UPDATE dbo.File_Mst
SET TTDExpenses = (SELECT SUM(c.Amount)FROM dbo.[Check Requests] c JOIN
dbo.File_Mst f
ON (f.FileNumber = c.FileNumber))
WHERE (f.FileTypeID = 3)

I am trying to update the column TTDExpense on File_Mst from the column
Amount on [Check Requests] for matching FileNumber fields.  Thanks.

David
SQL Server 2000
(1)
SQL Server 2005
(1)
VARCHARs
(1)
Ideas.UPDATE
(1)
Oracle
(1)
Deterministic
(1)
CREATE INDEX
(1)
CREATE TABLE
(1)
  mohitkgupt replied...
12-Jul-07 06:32 PM
UPDATE dbo.File_Mst
SET TTDExpenses = (SELECT SUM(c.Amount)FROM dbo.[Check Requests] c JOIN
dbo.File_Mst f
ON (f.FileNumber = c.FileNumber)
WHERE (f.FileTypeID = 3))

Brackets were wrong ..
--
Mohit K. Gupta
B.Sc. CS, Minor Japanese
MCTS: SQL Server 2005
  Roy Harvey replied...
12-Jul-07 06:45 PM
See if this gives you some ideas.

UPDATE dbo.File_Mst
SET TTDExpenses =
(SELECT SUM(c.Amount)
FROM dbo.[Check Requests] c
WHERE dbo.File_Mst.FileNumber = c.FileNumber)
WHERE dbo.File_Mst.FileTypeID = 3

Roy Harvey
Beacon Falls, CT

On Thu, 12 Jul 2007 17:12:09 -0500, "David C"
  Erland Sommarskog replied...
15-Jul-07 09:36 AM
David C (dlchase@lifetimeinc.com) writes:

You're lucky this time. But for the next occasion remember to explain
why it is not working, so that people do not have to guess.

The problem is that you have misunderstood the quite obscure ANSI
syntax for an update. You should not include the table you are
updating in the subquery, because then there will be no correlation
with the target table. Thus:

UPDATE dbo.File_Mst
SET     TTDExpenses = (SELECT SUM(c.Amount)
FROM   dbo.[Check Requests] c
WHERE  f.FileNumber = c.FileNumber)
FROM   dbo.File_Mst f
WHERE  f.FileTypeID = 3

Personally, I prefer the proprietary UPDATE FROM syntax:

UPDATE dbo.File_Mst
SET    TTDExpenses = c.Amount
FROM   dbo.File_Mst f
JOIN   (SELECT FileNumber, Amount = SUM(Amount)
FROM   [Check Requests]
GROUP  BY FileNumber) c ON  f.FileNumber = c.FileNumber
WHERE  f.FileTypeID = 3

My experience is also that this performs better.


--
Erland Sommarskog, SQL Server MVP, esquel@sommarskog.se

Books Online for SQL Server 2005 at
http://www.microsoft.com/technet/prodtechnol/sql/2005/downloads/books.mspx
Books Online for SQL Server 2000 at
http://www.microsoft.com/sql/prodinfo/previousversions/books.mspx
  --CELKO-- replied...
12-Jul-07 09:24 PM
Of course the proprietary, non-portable syntax can have unpredictable
results, but as long as it ifs fast, who cares?

Also the ANSI/ISO syntax is totally consistent with the model of SQL,
while the proprietary version makes no sense at all.  A FROM clause
creates a local working table, that disappears at the end of the
statement, etc. etc.

This guy migh have bad data element names (is he really mimicking a
tape file system in SQL, as the names imply?), but he is doing some
things right.
  Alex Kuznetsov replied...
12-Jul-07 09:43 PM
Just for the record. The reason lots of people go for the proprietary
UPDATE ... FROM is simple: the ANSI standard UPDATE sucks big time.
Note that Oracle also provides a proprietary UPDATE, which is also
very frequently used, and Oracle's UPDATE is also much better than the
ANSI standard one. Have you noticed the pattern?

Alex Kuznetsov, SQL Server MVP
http://sqlserver-tips.blogspot.com/
  Tony Rogerson replied...
13-Jul-07 02:25 AM
If the Standard implementation wasn't so lame and poor then people might use
it.

Really, what on earth where they thinking? How many systems only require an
update to a single field?

The majority of real systems update several dozen columns at once, you'd
require several dozen seperate sub queries/ queries using the Standard - a
failing you never mention.

--
Tony Rogerson, SQL Server MVP
http://sqlblogcasts.com/blogs/tonyrogerson
[Ramblings from the field from a SQL consultant]
http://sqlserverfaq.com
[UK SQL User Community]
  Erland Sommarskog replied...
15-Jul-07 09:36 AM
--CELKO-- (jcelko212@earthlink.net) writes:

Right. Who cares? Who should care? Only the unfortunate few who have
to care about being platform independent.


The proprietary syntax is very simlpe and intuitive to understand, and
simple to debug. The ANSI syntax is very difficult to understand and you
can easily go wrong with it. As testified by David's query.


--
Erland Sommarskog, SQL Server MVP, esquel@sommarskog.se

Books Online for SQL Server 2005 at
http://www.microsoft.com/technet/prodtechnol/sql/2005/downloads/books.mspx
Books Online for SQL Server 2000 at
http://www.microsoft.com/sql/prodinfo/previousversions/books.mspx
  Roy Harvey replied...
13-Jul-07 08:10 AM
On Fri, 13 Jul 2007 07:25:29 +0100, "Tony Rogerson"


The standard actually has an optional feature that avoids that problem
though it is not implemented in T-SQL.  It allows:

UPDATE X
SET (a, b, c) = (SELECT a, b, c FROM .....)

Of course you still have to code the WHERE clause so every other row
in the table is not updated when you don't want or need it to be, so
FROM still has significant advantages in simpler and cleaner coding.

Roy Harvey
Beacon Falls, CT
  David C replied...
13-Jul-07 08:49 AM
I agree with the bad data element names, but sometimes we are stuck with
what we "inherit" from others.

David
  J. M. De Moor replied...
18-Jul-07 01:28 AM
Prove it.  Once and for all, give us an example of a correctly coded
UPDATE..FROM that gives "unpredictable results."  Oh, and we already
shot your favorite "Adam Machanic" example (that Hugo denied ever having
anything to do with) and put it out of its misery a year ago.

...and if you once again choose to plant a bug in code that the compiler
won't catch, I will do the same with an ANSI-92 version of the
statement.  This tactic does not support your argument.

If you champion standards, good for you.  The industry needs those
voices.  But you are hurting yourself and doing a disservice to folks
who still look to you as authority when making scare-them-out-of-trying
statements like this that are simply untrue.
  --CELKO-- replied...
19-Jul-07 12:47 PM
Using SQL-2000

DROP TABLE OrderDetails, Orders;
CREATE TABLE Orders
(order_nbr INTEGER NOT NULL PRIMARY KEY,
some_col DECIMAL (9,2) NOT NULL);

INSERT INTO Orders VALUES (1, 0);
INSERT INTO Orders VALUES (2, 0);
INSERT INTO Orders VALUES (3, 0);

CREATE TABLE OrderDetails
(order_nbr INTEGER NOT NULL,
sku INTEGER NOT NULL,
item_price DECIMAL (9,2) NOT NULL,
PRIMARY KEY(order_nbr, sku),
-- FOREIGN KEY(sku) REFERENCES Products(sku)
FOREIGN KEY(order_nbr) REFERENCES Orders(order_nbr));

INSERT INTO OrderDetails VALUES (1, 1, 500.00);
INSERT INTO OrderDetails VALUES (1, 2, 205.00);
INSERT INTO OrderDetails VALUES (2, 1, 490.95);
INSERT INTO OrderDetails VALUES (3, 1, 480.00);

UPDATE Orders
SET Orders.some_col = OrderDetails.item_price
FROM Orders
INNER JOIN
OrderDetails
ON Orders.order_nbr = OrderDetails.order_nbr;

/*
results -
1	205.00  - where is the $500.00?
2	490.95
3	480.0
*/
--repeat with new physical ordering
DELETE FROM OrderDetails;
DELETE FROM Orders;
DROP INDEX OrderDetails.foobar;

--this will change the INNER JOIN
CREATE INDEX foobar ON OrderDetails (order_nbr, item_price);

INSERT INTO Orders VALUES (1, 0);
INSERT INTO Orders VALUES (2, 0);
INSERT INTO Orders VALUES (3, 0);

INSERT INTO OrderDetails VALUES (1, 2, 205.00);
INSERT INTO OrderDetails VALUES (1, 1, 500.00);
INSERT INTO OrderDetails VALUES (2, 1, 490.95);
INSERT INTO OrderDetails VALUES (3, 1, 480.00);

-- run it again
UPDATE Orders
SET Orders.some_col = OrderDetails.item_price
FROM Orders
INNER JOIN
OrderDetails
ON Orders.order_nbr = OrderDetails.order_nbr;

SELECT * FROM Orders;

/*
Results
1	500.00 -- now the other guy shows up!
2	490.95
3	480.00
*/

What property is most important in an INDEX?  Adding or dropping an
index changes performance but never, never changes results!

Since anyone can now cut & paste this into QA, and hit the F5 key, do
I even have to reply?


If you had worked with the original Sybase version of this syntax, you
would have been told it was a replacement for looping.  You would
written code like "SET Orders.some_col = Orders.some_col +
OrderDetails.item_price" to get a total.  This was never considered a
bug by the original creators, but the planned behavior
  Tony Rogerson replied...
19-Jul-07 04:48 PM
That is NOT correctly coded, you have a FUNDEMENTAL ERROR in it.

There is not a one to one relationship between Orders and OrderDetails so
your update WILL be unpredictable, this is documented in books online.

--
Tony Rogerson, SQL Server MVP
http://sqlblogcasts.com/blogs/tonyrogerson
[Ramblings from the field from a SQL consultant]
http://sqlserverfaq.com
[UK SQL User Community]
  Hugo Kornelis replied...
20-Jul-07 05:17 PM
(snip DDL)


Since you post this in reply to a request for a "correctly coded" UPDATE
FROM example, one has to assume that the requirement here was to set the
some_col column in the orders table equal to item_price from one of the
OrderDetails rows for the same order (with no specification for which
one), or to leave it unchanged if no OrderDetails exist for the order.
Any other requirement would have resulted in a differently coded UPDATE
statement.

Let's translate that to an equivalent ANSI UPDATE. I'll use SQL 2005, if
you don't mind, as the ROW_NUMBER() function makes this much easier than
it would be for SQL 2000. I have included the actual results, in case
you don't have access to a SQL 2005 server at the moment.


DROP TABLE OrderDetails, Orders;
CREATE TABLE Orders
(order_nbr INTEGER NOT NULL PRIMARY KEY,
some_col DECIMAL (9,2) NOT NULL);

INSERT INTO Orders VALUES (1, 0);
INSERT INTO Orders VALUES (2, 0);
INSERT INTO Orders VALUES (3, 0);

CREATE TABLE OrderDetails
(order_nbr INTEGER NOT NULL,
sku INTEGER NOT NULL,
item_price DECIMAL (9,2) NOT NULL,
PRIMARY KEY(order_nbr, sku),
-- FOREIGN KEY(sku) REFERENCES Products(sku)
FOREIGN KEY(order_nbr) REFERENCES Orders(order_nbr));

INSERT INTO OrderDetails VALUES (1, 1, 500.00);
INSERT INTO OrderDetails VALUES (1, 2, 205.00);
INSERT INTO OrderDetails VALUES (2, 1, 490.95);
INSERT INTO OrderDetails VALUES (3, 1, 480.00);

WITH OrderDetailsRanked
AS (SELECT order_nbr, item_price,
ROW_NUMBER() OVER (PARTITION BY order_nbr ORDER BY order_nbr)
AS rn
FROM   OrderDetails)
UPDATE Orders
SET    some_col = (SELECT od.item_price
FROM   OrderDetailsRanked AS od
WHERE  od.order_nbr = Orders.order_nbr
AND    od.rn = 1)
WHERE  EXISTS     (SELECT *
FROM   OrderDetailsRanked AS od
WHERE  od.order_nbr = Orders.order_nbr);

SELECT * FROM Orders

/*
results -
1	500.00  - where is the $205.00?
2	490.95
3	480.0
*/

--repeat with new physical ordering
--this will change the ROW_NUMBER()
CREATE INDEX foobar ON OrderDetails (order_nbr, item_price);

-- run it again
WITH OrderDetailsRanked
AS (SELECT order_nbr, item_price,
ROW_NUMBER() OVER (PARTITION BY order_nbr ORDER BY order_nbr)
AS rn
FROM   OrderDetails)
UPDATE Orders
SET    some_col = (SELECT od.item_price
FROM   OrderDetailsRanked AS od
WHERE  od.order_nbr = Orders.order_nbr
AND    od.rn = 1)
WHERE  EXISTS     (SELECT *
FROM   OrderDetailsRanked AS od
WHERE  od.order_nbr = Orders.order_nbr);

SELECT * FROM Orders;

/*
Results
1	205.00 -- now the other guy shows up!
2	490.95
3	480.00
*/


As you see, the ANSI compliant version is just as unpredictable as the
proprietary T-SQL version. Which, of course, makes sense - after all,
the requirement itself was undeterministic, so how could you ever even
expect a correct translation into SQL to somehow "make" this
deterministic?

--
Hugo Kornelis, SQL Server MVP
My SQL Server blog: http://sqlblog.com/blogs/hugo_kornelis
  Alex Kuznetsov replied...
20-Jul-07 06:06 PM
Hugo,

BRAVO!

Alex Kuznetsov, SQL Server MVP
http://sqlserver-tips.blogspot.com/
  J. M. De Moor replied...
20-Jul-07 08:41 PM
I stand corrected.  I didn't realize that you were trying to update an
order with a value from any single order detail WITHOUT QUALIFIERS as
long as it is the same detail every single time.  I do not know how to
code that in ANSI 92 SQL.

On the other hand, how did you know that $500 was the right answer?
See, by this example you are in effect telling people stay away from ANY
UPDATE statement because the following code won't give you the results
you want:

SET last_name = city

After all, how many cities out there are named after people?  Both are
VARCHARs so we better not use UPDATE at all because jr programmer might
make a mistake like this and $2K-a-day consultant may have to find it
for him.

You didn't prove your point; you planted a bug!  WHO CARES IF BUGGY CODE
GIVES "UNPREDICTABLE" RESULTS??!?  I don't.  Fix the bug.

Joe
Create New Account
help
SSIS / DTS with SQL Server 2000? SQL Server I am working with a SQL Server 2005 client while the server still runs SQL Server 2000. SQL Server 2000 had DTS while 2005 has SSIS. Given
SQL server 2000 SQL Server Does Microsoft still support SQL server 2000? SQL Server New Users Discussions SQL Server (1) SQL Server Books Online (1) SQL server
Attach SQL Server 2008 database to SQL Server 2000 Server SQL Server Hi, I have created a database in SQL Server 2008, with compatibility level of SQL
SQL Server 2000 SQL Server Are there any compatability issues with SQL Server 2000 Enterprise edition and Server 2003 standard with SP2? SQL Server Discussions SQL Server 2000 (1
Problem upgrade sql server 6.5 to sql server 2000 enterprise edition on Windows 2000 Server SQL Server Hello, I have problems with upgrade sql server 6.5 to sql server 2000