Thread: UPDATE of several columns using SELECT statement
Hello,
I am facing the following problem, nothing tough, I guess (hope)….think it should be some syntactical problem:
1. When trying to update two columns
UPDATE myFirstTable SET (fistCol, secCol) = ( SELECT anotherFistCol, anotherSecondCol FROM mySecondTable )
I am getting: ERROR: syntax error at or near "select"
2. When changed to (only the parentheses are changed):
UPDATE myFirstTable SET (fistCol, secCol) = (( SELECT anotherFistCol, anotherSecondCol FROM mySecondTable ))
I am getting: ERROR: number of columns does not match number of values
Does anybody know, what I am doing wrong? Thank you very much and wish you a luxurious day
Adam
On Tue, Mar 17, 2009 at 03:55:47PM +0100, adam.slachta wrote: > 1. When trying to update two columns > > UPDATE myFirstTable SET (fistCol, secCol) = ( SELECT anotherFistCol, anotherSecondCol FROM mySecondTable ) The more common say of expressing this would be something like: UPDATE myFirstTable a SET fistCol = b.anotherFistCol, secCol = b.anotherSecondCol FROM mySecondTable b WHERE a.expr = b.expr; > 2. When changed to (only the parentheses are changed): > > UPDATE myFirstTable SET (fistCol, secCol) = ((SELECT anotherFistCol, anotherSecondCol FROM mySecondTable )) > > I am getting: ERROR: number of columns does not match number of values PG is somewhat ad-hoc with its support of its record syntax and unfortunately doesn't support the above at the moment. The error is coming from very early on (I think maybe when parsing) and I don't think it ever gets as far as checking that the value coming back from the select is a record of the same structure as is on the left hand side. -- Sam http://samason.me.uk/
adam.slachta wrote: > > 1. When trying to update two columns > > UPDATE myFirstTable SET (fistCol, secCol) = ( SELECT anotherFistCol, > anotherSecondCol FROM mySecondTable ) In addition to Sam's reply what you've got there would never work anyway unless mySecondTable only contains one row. You'd need a join. Like Sam says though, we don't support that syntax. -- Richard Huxton Archonet Ltd
Well, I should have been more specific and not use such a simplified example, which only lead you into wrong direction. What I am really tried to solve instead of
UPDATE myFirstTable SET (fistCol, secCol) = ( SELECT anotherFistCol, anotherSecondCol FROM mySecondTable )
is this:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
UPDATE limit_breach lb
SET (max_breach, limit_value) =
((
SELECT ABS(ov.outright_volume) - NVL(ov.hedge_limit,0), hedge_limit
FROM
(
outrightvolume_breach
)
ov
WHERE ov.hedging_desk=lb.hedging_desk
AND ov.idmarket = lb.idmarket
AND ov.symbol = lb.symbol
AND ov.limit_name = lb.limit_name
AND lb.breach_end IS NULL
))
WHERE
lb.breach_end IS NULL
AND
(lb.hedging_desk, lb.idmarket, lb.symbol, lb.limit_name)
IN
(
SELECT hedging_desk, idmarket, symbol, limit_name
FROM
(
outrightvolume_breach
) ov
WHERE (ABS(ov.outright_volume) - NVL(ov.hedge_limit,0)) > lb.max_breach
) ;
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Do you think there might be a way how to solve this not leading into splitting the update into two separate update statements for each of the two columns (max_breach, limit_value) ?
Adam
On Tue, Mar 17, 2009 at 05:57:01PM +0100, adam.slachta wrote: > Do you think there might be a way how to solve this not leading into > splitting the update into two separate update statements for each of the two > columns (max_breach, limit_value) ? That's quite a query; I'm guessing it's from Oracle as it refers to a NVL function and that this should be translated into COALESCE for PG. Would the following do what you want: UPDATE limit_breach lb SET limit_value = ov.hedge_limit, max_breach = ov.max_breach FROM ( SELECT hedging_desk, idmarket, symbol, limit_name, hedge_limit, ABS(ov.outright_volume) - COALESCE(ov.hedge_limit,0) AS max_breach FROM outrightvolume_breach) ov WHERE lb.hedging_desk = ov.hedging_desk AND lb.idmarket = ov.idmarket AND lb.symbol = ov.symbol AND lb.limit_name = ov.limit_name AND lb.breach_end IS NULL AND lb.max_breach <= ov.max_breach; I've obviously not tested it, but I think it's correct. It's also got the advantage of much less duplication of code. -- Sam http://samason.me.uk/