Обсуждение: 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/