How to update rows from a cursor in PostgreSQL

Started by Rubenabout 23 years ago8 messagesgeneral
Jump to latest
#1Ruben
ruben12@superguai.com

I was trying something like:

select * from t1, t2, t3, t4
where ...
for update of t1

while(fetch...)
{
update
where current
}

Since "FOR UPDATE" cursors are not supported in PostgreSQL, can I update
the current row of table t1?

Thanks a lot!

#2Peter Eisentraut
peter_e@gmx.net
In reply to: Ruben (#1)
Re: How to update rows from a cursor in PostgreSQL

Ruben writes:

Since "FOR UPDATE" cursors are not supported in PostgreSQL, can I update
the current row of table t1?

There is no direct way, but some interfaces (e.g., ODBC, JDBC) emulate
updatable cursors in the client.

--
Peter Eisentraut peter_e@gmx.net

#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Ruben (#1)
Re: How to update rows from a cursor in PostgreSQL

Ruben <ruben12@superguai.com> writes:

Since "FOR UPDATE" cursors are not supported in PostgreSQL, can I update
the current row of table t1?

The usual hack for this is to select the table's "ctid" system column as
part of the cursor output, and then say

UPDATE t1 SET ... WHERE ctid = 'what-you-got-from-the-cursor';

This is quite fast because the ctid is essentially a physical locator.
Note however that it will fail (do nothing) if someone else has already
updated the same row since your transaction started. This may or may
not be what you want. I think ODBC has some hack to find the ctid of
the latest version of the row.

regards, tom lane

#4Emmanuel Charpentier
charpent@bacbuc.dyndns.org
In reply to: Tom Lane (#3)
Re: How to update rows from a cursor in PostgreSQL

Tom Lane wrote:

Ruben <ruben12@superguai.com> writes:

Since "FOR UPDATE" cursors are not supported in PostgreSQL, can I update
the current row of table t1?

The usual hack for this is to select the table's "ctid" system column as
part of the cursor output, and then say

UPDATE t1 SET ... WHERE ctid = 'what-you-got-from-the-cursor';

This is quite fast because the ctid is essentially a physical locator.
Note however that it will fail (do nothing) if someone else has already
updated the same row since your transaction started. This may or may
not be what you want. I think ODBC has some hack to find the ctid of
the latest version of the row.

However, it should be noted that this may fail, especially if you work on
views. I've been bitten by this.

Emmanuel Charpentier

--
Emmanuel Charpentier

#5Shridhar Daithankar
shridhar_daithankar@persistent.co.in
In reply to: Emmanuel Charpentier (#4)
Re: How to update rows from a cursor in PostgreSQL

On Saturday 22 Feb 2003 2:08 pm, you wrote:

Tom Lane wrote:

Ruben <ruben12@superguai.com> writes:

Since "FOR UPDATE" cursors are not supported in PostgreSQL, can I update
the current row of table t1?

The usual hack for this is to select the table's "ctid" system column as
part of the cursor output, and then say

UPDATE t1 SET ... WHERE ctid = 'what-you-got-from-the-cursor';

This is quite fast because the ctid is essentially a physical locator.
Note however that it will fail (do nothing) if someone else has already
updated the same row since your transaction started. This may or may
not be what you want. I think ODBC has some hack to find the ctid of
the latest version of the row.

However, it should be noted that this may fail, especially if you work on
views. I've been bitten by this.

Just wondering, is updatable views a TODO for postgresql?

Shridhar

#6Ruben
ruben12@superguai.com
In reply to: Ruben (#1)
Re: How to update rows from a cursor in PostgreSQL

Thanks a lot Tom:

Shouldn't it be better then to use "oid" instead of ctid?

Ruben.

Tom Lane wrote:

Show quoted text

Ruben <ruben12@superguai.com> writes:

Since "FOR UPDATE" cursors are not supported in PostgreSQL, can I update
the current row of table t1?

The usual hack for this is to select the table's "ctid" system column as
part of the cursor output, and then say

UPDATE t1 SET ... WHERE ctid = 'what-you-got-from-the-cursor';

This is quite fast because the ctid is essentially a physical locator.
Note however that it will fail (do nothing) if someone else has already
updated the same row since your transaction started. This may or may
not be what you want. I think ODBC has some hack to find the ctid of
the latest version of the row.

#7Tom Lane
tgl@sss.pgh.pa.us
In reply to: Ruben (#6)
Re: How to update rows from a cursor in PostgreSQL

Ruben <ruben12@superguai.com> writes:

Shouldn't it be better then to use "oid" instead of ctid?

Only if you (a) have an OID column and (b) have a unique index created
on the OID column. ctid is nice because it doesn't incur any indexing
overhead ...

regards, tom lane

#8Bruce Momjian
bruce@momjian.us
In reply to: Tom Lane (#3)
Re: How to update rows from a cursor in PostgreSQL

Tom Lane wrote:

Ruben <ruben12@superguai.com> writes:

Since "FOR UPDATE" cursors are not supported in PostgreSQL, can I update
the current row of table t1?

The usual hack for this is to select the table's "ctid" system column as
part of the cursor output, and then say

UPDATE t1 SET ... WHERE ctid = 'what-you-got-from-the-cursor';

This is quite fast because the ctid is essentially a physical locator.
Note however that it will fail (do nothing) if someone else has already
updated the same row since your transaction started. This may or may
not be what you want. I think ODBC has some hack to find the ctid of
the latest version of the row.

We do have this in TODO:

o Allow UPDATE/DELETE WHERE CURRENT OF cursor using per-cursor tid
stored in the backend

Tom, if they do FOR UPDATE in the cursor, no one else can modify the row
until the transaction commits, right? I assume FOR UPDATE it required
for this functionality.

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073