Update violating constraint

Started by Naz Gassiepalmost 19 years ago11 messagesgeneral
Jump to latest
#1Naz Gassiep
naz@mira.net

Hi,
I'm trying to do an update on a table that has a unique constraint
on the field, I need to update the table by setting field = field+1
however if this does not perform the updates on the table in a proper
order (from last to first) then the update will cause a violation of the
index *during* the update even though the table would be consistent
after the update completes. So the update fails. How do I get around
this without removing the constraint?
- Naz.

#2Michael Glaesemann
grzm@seespotcode.net
In reply to: Naz Gassiep (#1)
Re: Update violating constraint

On May 2, 2007, at 23:01 , Naz Gassiep wrote:

I'm trying to do an update on a table that has a unique constraint
on the field, I need to update the table by setting field = field+1
however if this does not perform the updates on the table in a proper
order (from last to first) then the update will cause a violation
of the
index *during* the update even though the table would be consistent
after the update completes.

If field's values are all positive, I generally will do it in two steps:

update foo
set field = -1 * (field + 1);
update foo
set field = -1 * field
where field < 0;

Another way to do it is to add and then remove a large offset:

update foo
set field = 100000 * (field + 1);
update foo
set field = field - 100000
where field > 100000;

Does either of these help?

Michael Glaesemann
grzm seespotcode net

#3Naz Gassiep
naz@mira.net
In reply to: Michael Glaesemann (#2)
Re: Update violating constraint

Michael Glaesemann wrote:

On May 2, 2007, at 23:01 , Naz Gassiep wrote:

I'm trying to do an update on a table that has a unique constraint
on the field, I need to update the table by setting field = field+1
however if this does not perform the updates on the table in a proper
order (from last to first) then the update will cause a violation of the
index *during* the update even though the table would be consistent
after the update completes.

If field's values are all positive, I generally will do it in two steps:

update foo
set field = -1 * (field + 1);
update foo
set field = -1 * field
where field < 0;

Another way to do it is to add and then remove a large offset:

update foo
set field = 100000 * (field + 1);
update foo
set field = field - 100000
where field > 100000;

Yes, in fact I actually use option one already in the handling of sql
trees, so I'm annoyed with myself for not figuring that out. I don't
know why you'd ever use your second option ever, as it virtually
guarantees problems at a random point in your DB's growth.

Thanks muchly for that!

#4Alban Hertroys
alban@magproductions.nl
In reply to: Naz Gassiep (#1)
Re: Update violating constraint

Naz Gassiep wrote:

Hi,
I'm trying to do an update on a table that has a unique constraint
on the field, I need to update the table by setting field = field+1
however if this does not perform the updates on the table in a proper
order (from last to first) then the update will cause a violation of the
index *during* the update even though the table would be consistent
after the update completes. So the update fails. How do I get around
this without removing the constraint?

I think you're looking for deferrable constraints; see:

http://www.postgresql.org/docs/8.2/static/sql-set-constraints.html

--
Alban Hertroys
alban@magproductions.nl

magproductions b.v.

T: ++31(0)534346874
F: ++31(0)534346876
M:
I: www.magproductions.nl
A: Postbus 416
7500 AK Enschede

// Integrate Your World //

#5Richard Huxton
dev@archonet.com
In reply to: Alban Hertroys (#4)
Re: Update violating constraint

Alban Hertroys wrote:

Naz Gassiep wrote:

Hi,
I'm trying to do an update on a table that has a unique constraint
on the field, I need to update the table by setting field = field+1

I think you're looking for deferrable constraints; see:

http://www.postgresql.org/docs/8.2/static/sql-set-constraints.html

Which won't work with unique constraints unfortunately. That's because
they're implemented through a unique index.

The work-around is to do: field = -field then field = -field + 1 or similar.

--
Richard Huxton
Archonet Ltd

#6Michael Glaesemann
grzm@seespotcode.net
In reply to: Naz Gassiep (#3)
Re: Update violating constraint

On May 2, 2007, at 23:36 , Naz Gassiep wrote:

I don't
know why you'd ever use your second option ever, as it virtually
guarantees problems at a random point in your DB's growth.

There may be cases where the values are not all positive so you can't
use the -1 * technique, but the offset will work. It depends on the
nature of your data. One size doesn't necessarily fit all.

Michael Glaesemann
grzm seespotcode net

#7Richard Broersma Jr
rabroersma@yahoo.com
In reply to: Naz Gassiep (#3)
Re: Update violating constraint

update foo
set field = -1 * (field + 1);
update foo
set field = -1 * field
where field < 0;

Yes, in fact I actually use option one already in the handling of sql
trees, so I'm annoyed with myself for not figuring that out. I don't
know why you'd ever use your second option ever, as it virtually
guarantees problems at a random point in your DB's growth.

If you are updating a large portion of your tree, you will probably want to throw in a vacuum in
between the two updates. This should reduce the bloat caused by dead tuples in both your index
and table.

Regards,
Richard Broersma Jr.

#8Csaba Nagy
nagy@ecircle-ag.com
In reply to: Richard Broersma Jr (#7)
Re: Update violating constraint

If you are updating a large portion of your tree, you will probably want to throw in a vacuum in
between the two updates. This should reduce the bloat caused by dead tuples in both your index
and table.

... but that will only work if you can commit the first set of changes
before you get to the end result, possibly having an inconsistent state
for the duration of the vacuum... if you want all in one transaction,
vacuum will not help.

Cheers,
Csaba.

#9Alban Hertroys
alban@magproductions.nl
In reply to: Richard Huxton (#5)
Re: Update violating constraint

Richard Huxton wrote:

Alban Hertroys wrote:

Naz Gassiep wrote:

Hi,
I'm trying to do an update on a table that has a unique constraint
on the field, I need to update the table by setting field = field+1

I think you're looking for deferrable constraints; see:

http://www.postgresql.org/docs/8.2/static/sql-set-constraints.html

Which won't work with unique constraints unfortunately. That's because
they're implemented through a unique index.

I appreciate the complexities involved, but that really ought to work on
a single statement. I recall seeing something along these lines on the
TODO list some time ago?

--
Alban Hertroys
alban@magproductions.nl

magproductions b.v.

T: ++31(0)534346874
F: ++31(0)534346876
M:
I: www.magproductions.nl
A: Postbus 416
7500 AK Enschede

// Integrate Your World //

#10Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Alban Hertroys (#9)
Re: Update violating constraint

Alban Hertroys wrote:

Richard Huxton wrote:

Alban Hertroys wrote:

Naz Gassiep wrote:

Hi,
I'm trying to do an update on a table that has a unique constraint
on the field, I need to update the table by setting field = field+1

I think you're looking for deferrable constraints; see:

http://www.postgresql.org/docs/8.2/static/sql-set-constraints.html

Which won't work with unique constraints unfortunately. That's because
they're implemented through a unique index.

I appreciate the complexities involved, but that really ought to work on
a single statement. I recall seeing something along these lines on the
TODO list some time ago?

It is still on the TODO list. If you want it to disappear from there,
your best bet is implementing a fix, followed by motivating someone to
do it for you. If you don't, bets are someone will do it eventually
(which may be too late for your taste).

--
Alvaro Herrera http://www.CommandPrompt.com/
PostgreSQL Replication, Consulting, Custom Development, 24x7 support

#11Bruce Momjian
bruce@momjian.us
In reply to: Alvaro Herrera (#10)
Re: Update violating constraint

Alvaro Herrera wrote:

Alban Hertroys wrote:

Richard Huxton wrote:

Alban Hertroys wrote:

Naz Gassiep wrote:

Hi,
I'm trying to do an update on a table that has a unique constraint
on the field, I need to update the table by setting field = field+1

I think you're looking for deferrable constraints; see:

http://www.postgresql.org/docs/8.2/static/sql-set-constraints.html

Which won't work with unique constraints unfortunately. That's because
they're implemented through a unique index.

I appreciate the complexities involved, but that really ought to work on
a single statement. I recall seeing something along these lines on the
TODO list some time ago?

It is still on the TODO list. If you want it to disappear from there,
your best bet is implementing a fix, followed by motivating someone to
do it for you. If you don't, bets are someone will do it eventually
(which may be too late for your taste).

Yes, TODO has:

o Allow DEFERRABLE and end-of-statement UNIQUE constraints?

This would allow UPDATE tab SET col = col + 1 to work if col has
a unique index. Currently, uniqueness checks are done while the
command is being executed, rather than at the end of the statement
or transaction.
http://people.planetpostgresql.org/greg/index.php?/archives/2006/06/10.html
http://archives.postgresql.org/pgsql-hackers/2006-09/msg01458.php

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://www.enterprisedb.com

+ If your life is a hard drive, Christ can be your backup. +