I want to add a sequence to a column that might already have data, so I'm trying to start it beyond whatever's already there. Assuming there already is data, I would like to have done it this way:
CREATE SEQUENCE my_sequence MINVALUE 1000000 START
(SELECT MAX(id_column) FROM my_table) OWNED BY my_table.id_column;
but it keeps dying at ( claiming syntax error. It's like the start value has to be cold hard numbers--nothing symbolic.
Of course, an even better solution would be if the sequence could be intelligent enough to avoid duplicate values, since id_column has a unique constraint on it--that's why I'm doing this. But from what I can tell, that's not possible.
I also tried skipping the START and then doing:
ALTER SEQUENCE my_sequence RESTART WITH (SELECT max(id_column)+1 FROM my_table);
but, again, it doesn't seem like to symbolic start values.
I'm running PostgreSQL 9.4 but some of our customers are using stuff as primitive as 8.3.
You can't specify a dynamic value for the start value.
But you can set the value once the sequence is created:
CREATE SEQUENCE my_sequence MINVALUE 1000000 OWNED BY my_table.id_column;
select setval('my_sequence', (SELECT MAX(id_column) FROM my_table));
You can restore you sequence by request:
select setval('my_sequence', (SELECT MAX(id_column) FROM my_table));
Applicable for Postgres 9.2.
Just because I was struggling with a slight variation in use case to the accepted answers here and experiencing an error telling me that setval did not exist, thought I'd share in case others had the same.
I needed to set the value of my sequence to the max value in an id column, but I also wanted to combine that with a default starting value if there were no rows.
To do this I used coalesce combined with max like this:
select setval('sequence', cast((select coalesce(max(id),1) from table) as bigint));
The catch here was using cast with the select, without that, you get an error something like:
ERROR: function setval(unknown, double precision) does not exist
LINE 1: select setval('sequence', (select coalesce(MAX(i...
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
Related
I'm having troubles resetting the sequences as automatically as possible.
I'm trying to use the next query from phpPgAdmin:
SELECT SETVAL('course_subjects_seq', (SELECT MAX(subject_id) FROM course_subjects));
Somehow this query returns:
> HINT: No function matches the given name and argument types. You might need to add explicit type casts.
pointing to the first SELECT SETVAL
The next query will give the same error:
SELECT setval("course_subjects_seq", COALESCE((SELECT MAX(subject_id) FROM course_subjects), 1))
Can anyone point me to what am I doing wrong?
Fixed by doing so:
setval function requires regclass, bigint and boolean as arguments, therefore I added the type casts:
SELECT setval('course_subjects_seq'::regclass, COALESCE((SELECT MAX(subject_id) FROM course_subjects)::bigint, 1));
::regclass
and ::bigint
You don't need a subquery at all here. Can be a single SELECT:
SELECT setval(pg_get_serial_sequence('course_subjects', 'subject_id')
, COALESCE(max(subject_id) + 1, 1)
, false) -- not called yet
FROM course_subjects;
Assuming subject_id is a serial column, pg_get_serial_sequence() is useful so you don't have to know the sequence name (which is an implementation detail, really).
SELECT with an aggregate function like max() always returns a single row, even if the underlying table has no rows. The value is NULL in this case, that's why you have COALESCE in there.
But if you call setval() with 1, the next sequence returned number will be 2, not 1, since that is considered to be called already. There is an overloaded variant of setval() with a 3rd, boolean parameter: is_called, which makes it possible to actually start from 1 in this case like demonstrated.
Related:
How to reset postgres' primary key sequence when it falls out of sync?
I have to change the value of a determined column in postgre but I never worked before with maskbits, (it's a legacy code). The current value is 1 but it's stored as a integer maskbit so if I try to do
update table set field=0 where ...
It doesn't work and it keeps returning me 1. So I read the documentation and tried to do a AND:
update table set field=field&0 where ...
But it doesn't worked too. Then I tried to cover all the 30 bits, without success too:
update table set field=field&0000000000000000000000000000000 where ...
Can someone please show me how to properly change the value of a integer maskbit on postgresql?
EDIT: I found this case here in StackOverflow
UPDATE users SET permission = permission & ~16
which seen's to be the closest to mine so I tried to do
UPDATE table SET field = field & ~1
because that's the only bit I have to deactivate but it still active and retuning 1 when I do a SELECT
PostgreSQL may be pickier than you're used to when it comes to combining numbers of different types. You can't just use a 0, you need to use a bitstring constant of the right length, or explicitly cast an integer to the proper bit(n) type.
Bitstring constants are entered like B'00101', which would have type bit(5).
Some examples you can type into psql:
select 5;
select (5::bit(5));
select (30::bit(5));
select ~(1::bit(5));
select ~B'00001';
select (B'00101' & B'11110');
select (B'00101' & ~(1::bit(5)));
I want to add a sequence to a column that might already have data, so I'm trying to start it beyond whatever's already there. Assuming there already is data, I would like to have done it this way:
CREATE SEQUENCE my_sequence MINVALUE 1000000 START
(SELECT MAX(id_column) FROM my_table) OWNED BY my_table.id_column;
but it keeps dying at ( claiming syntax error. It's like the start value has to be cold hard numbers--nothing symbolic.
Of course, an even better solution would be if the sequence could be intelligent enough to avoid duplicate values, since id_column has a unique constraint on it--that's why I'm doing this. But from what I can tell, that's not possible.
I also tried skipping the START and then doing:
ALTER SEQUENCE my_sequence RESTART WITH (SELECT max(id_column)+1 FROM my_table);
but, again, it doesn't seem like to symbolic start values.
I'm running PostgreSQL 9.4 but some of our customers are using stuff as primitive as 8.3.
You can't specify a dynamic value for the start value.
But you can set the value once the sequence is created:
CREATE SEQUENCE my_sequence MINVALUE 1000000 OWNED BY my_table.id_column;
select setval('my_sequence', (SELECT MAX(id_column) FROM my_table));
You can restore you sequence by request:
select setval('my_sequence', (SELECT MAX(id_column) FROM my_table));
Applicable for Postgres 9.2.
Just because I was struggling with a slight variation in use case to the accepted answers here and experiencing an error telling me that setval did not exist, thought I'd share in case others had the same.
I needed to set the value of my sequence to the max value in an id column, but I also wanted to combine that with a default starting value if there were no rows.
To do this I used coalesce combined with max like this:
select setval('sequence', cast((select coalesce(max(id),1) from table) as bigint));
The catch here was using cast with the select, without that, you get an error something like:
ERROR: function setval(unknown, double precision) does not exist
LINE 1: select setval('sequence', (select coalesce(MAX(i...
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
I have a simple question, suppose we have a table:
id A B
1 Jon Doe
2 Foo Bar
Is there a way to know, which is the next id's increment, in this case 3 ?
Database is PostgreSQL!
Tnx alot!
If you want to claim an ID and return it, you can use nextval(), which advances the sequence without inserting any data.
Note that if this is a SERIAL column, you need to find the sequence's name based on the table and column name, as follows:
Select nextval(pg_get_serial_sequence('my_table', 'id')) as new_id;
There is no cast-iron guarantee that you'll see these IDs come back in order (the sequence generates them in order, but multiple sessions can claim an ID and not use it yet, or roll back an INSERT and the ID will not be reused) but there is a guarantee that they will be unique, which is normally the important thing.
If you do this often without actually using the ID, you will eventually use up all the possible values of a 32-bit integer column (i.e. reach the maximum representable integer), but if you use it only when there's a high chance you will actually be inserting a row with that ID it should be OK.
To get the current value of a sequence without affecting it or needing a previous insert in the same session, you can use;
SELECT last_value FROM tablename_fieldname_seq;
An SQLfiddle to test with.
Of course, getting the current value will not guarantee that the next value you'll get is actually last_value + 1 if there are other simultaneous sessions doing inserts, since another session may have taken the serial value before you.
SELECT currval('names_id_seq') + 1;
See the docs
However, of course, there's no guarantee that it's going to be your next value. What if another client grabs it before you? You can though reserve one of the next values for yourself, selecting a nextval from the sequence.
I'm new so here's the process I use having little to no prior knowledge of how Postgres/SQL work:
Find the sequence for your table using pg_get_serial_sequence()
SELECT pg_get_serial_sequence('person','id');
This should output something like public.person_id_seq. person_id_seq is the sequence for your table.
Plug the sequence from (1) into nextval()
SELECT nextval('person_id_seq');
This will output an integer value which will be the next id added to the table.
You can turn this into a single command as mentioned in the accepted answer above
SELECT nextval(pg_get_serial_sequence('person','id'));
If you notice that the sequence is returning unexpected values, you can set the current value of the sequence using setval()
SELECT setval(pg_get_serial_sequence('person','id'),1000);
In this example, the next call to nextval() will return 1001.
How is it possible to get the current sequence value in postgresql 8.4?
Note: I need the value for the some sort of statistics, just retrieve and store. Nothing related to the concurrency and race conditions in case of manually incrementing it isn't relevant to the question.
Note 2: The sequence is shared across several tables
Note 3: currval won't work because of:
Return the value most recently obtained by nextval for this sequence in the current session
ERROR: currval of sequence "<sequence name>" is not yet defined in this session
My current idea: is to parse DDL, which is weird
You may use:
SELECT last_value FROM sequence_name;
Update:
this is documented in the CREATE SEQUENCE statement:
Although you cannot update a sequence directly, you can use a query
like:
SELECT * FROM name;
to examine the parameters and current state of a
sequence. In particular, the last_value field of the sequence shows
the last value allocated by any session. (Of course, this value might
be obsolete by the time it's printed, if other sessions are actively
doing nextval calls.)
If the sequence is being used for unique ids in a table, you can simply do this:
select max(id) from mytable;
The most efficient way, although postgres specific, is:
select currval('mysequence');
although technically this returns the last value generated by the call to nextval('mysequence'), which may not necessarily be used by the caller (and if unused would leave gaps in an auto increments id column).
As of some point in time, a secret function (which is undocumented ... still), does exactly this:
SELECT pg_sequence_last_value('schema.your_sequence_name');