Thread: How to update rows from a cursor in PostgreSQL

How to update rows from a cursor in PostgreSQL

From
Ruben
Date:
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!


Re: How to update rows from a cursor in PostgreSQL

From
Peter Eisentraut
Date:
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


Re: How to update rows from a cursor in PostgreSQL

From
Tom Lane
Date:
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

Re: How to update rows from a cursor in PostgreSQL

From
Emmanuel Charpentier
Date:
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


Re: How to update rows from a cursor in PostgreSQL

From
"Shridhar Daithankar"
Date:
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

Re: How to update rows from a cursor in PostgreSQL

From
Ruben
Date:
Thanks a lot Tom:

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

Ruben.



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.



Re: How to update rows from a cursor in PostgreSQL

From
Tom Lane
Date:
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

Re: How to update rows from a cursor in PostgreSQL

From
Bruce Momjian
Date:
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