views:

103

answers:

4

Is there a way to keep 2 sequences synchronized in Postgres?

I mean if I have:

table_A_id_seq = 1
table_B_id_seq = 1

if I execute SELECT nextval('table_A_id_seq'::regclass)

I want that table_B_id_seq takes the same value of table_A_id_seq

and obviously it must be the same on the other side.

I need 2 different sequences because I have to hack some constraints I have in Django (and that I cannot solve there).

A: 

You could put an INSERT trigger on Table_A that executes some code that increases Table_B's sequence. Now, every time you insert a new row into Table_A, it will fire off that trigger.

ryeguy
Doesn't work, sequences are not transaction safe. If one query fails, one sequence is updated, the other might not be. You can't do this with a trigger.
Frank Heikens
A: 

My first thought when seeing this is why do you really want to do this? This smells a little spoiled, kinda like milk does after being a few days expired.

What is the scenario that requires that these two seq stay at the same value?

Ignoring the "this seems a bit odd" feelings I'm getting in my stomach you could try this:

Put a trigger on table_a that does this on insert. --set b seq to the value of a.

select setval('table_b_seq',currval('table_a_seq'));

The problem with this approach is that is assumes only a insert into table_a will change the table_a_seq value and nothing else will be incrementing table_a_seq. If you can live with that this may work in a really hackish fashion that I wouldn't release to production if it was my call.

If you really need this, to make it more robust make a single interface to increment table_a_seq such as a function. And only allow manipulation of table_a_seq via this function. That way there is one interface to increment table_a_seq and you should also put select setval('table_b_seq',currval('table_a_seq')); into that function. That way no matter what, table_b_seq will always be set to be equal to table_a_seq. That means removing any grants to the users to table_a_seq and only granting them execute grant on the new function.

StarShip3000
A: 

Just use one sequence for both tables. You can't keep them in sync unless you always sync them again and over again. Sequences are not transaction safe, they always roll forwards, never backwards, not even by ROLLBACK.

Edit: one sequence is also not going to work, doesn't give you the same number for both tables. Use a subquery to get the correct number and use just a single sequence for a single table. The other table has to use the subquery.

Frank Heikens
+1  A: 

The two tables must be related in some way? I would encapsulate that relationship in a lookup table containing the sequence and then replace the two tables you expect to be handling with views that use the lookup table.

youngthing