pg_dump setting of sequences
Asked Answered
C

3

4

I've recently started developing apps with PostgreSQL as backend DB (imposed on me) with no previous experience of Postgres. So far it hasn't been too bad, but now I run into a problem to which I cannot find answer for.

I created a batch scripts that runs a pg_dump command for a particular database on the server. This batch file is executed on schedule by the pgAgent.

The pg_dump itself seems to work ok. All the database structure and data are dumped to a file. However the sequences are all set to 1. For example for table tbl_departments the sequence dump looks like this:

CREATE SEQUENCE "tbl_departments_iID_seq"
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;


ALTER TABLE "tbl_departments_iID_seq" OWNER TO postgres;

ALTER SEQUENCE "tbl_departments_iID_seq" OWNED BY tbl_departments."iID";

In this particular example the sequence should be set to start with 8, since the last inserted record has iID = 7.

How do I make the pg_dump set the sequence starting number the next one available for each table?

The command for dump is: %PGBIN%pg_dump -h 192.168.0.112 -U postgres -F p -b -v --inserts -f "\\192.168.0.58\PostgresDB\backup\internals_db.sql" Internals

EDIT:

I think I have found the issue, although I still don't know how to resolve this: If I open pgAdmin and generate CREATE script for tbl_departments, it look like this:

CREATE TABLE tbl_departments
(
  "iID" serial NOT NULL, -- id, autoincrement
  "c150Name" character varying(150) NOT NULL, -- human readable name for department
  "bRetired" boolean NOT NULL DEFAULT false, -- if TRUE that it is no longer active
  "iParentDept" integer NOT NULL DEFAULT 0, -- ID of the parent department
  CONSTRAINT tbl_departments_pkey PRIMARY KEY ("iID")
)

The pg_dump statement is:

    CREATE TABLE tbl_departments (
        "iID" integer NOT NULL,
        "c150Name" character varying(150) NOT NULL,
        "bRetired" boolean DEFAULT false NOT NULL,
        "iParentDept" integer DEFAULT 0 NOT NULL
    );


    ALTER TABLE tbl_departments OWNER TO postgres;

    COMMENT ON TABLE tbl_departments IS 'list of departments';

    COMMENT ON COLUMN tbl_departments."iID" IS 'id, autoincrement';

    COMMENT ON COLUMN tbl_departments."c150Name" IS 'human readable name for department';


    COMMENT ON COLUMN tbl_departments."bRetired" IS 'if TRUE that it is no longer active';

    COMMENT ON COLUMN tbl_departments."iParentDept" IS 'ID of the parent department';

    CREATE SEQUENCE "tbl_departments_iID_seq"
        START WITH 1
        INCREMENT BY 1
        NO MINVALUE
        NO MAXVALUE
        CACHE 1;

        ALTER TABLE "tbl_departments_iID_seq" OWNER TO postgres;

        ALTER SEQUENCE "tbl_departments_iID_seq" OWNED BY tbl_departments."iID";

    INSERT INTO tbl_departments VALUES (1, 'Information Technologies', false, 0);
    INSERT INTO tbl_departments VALUES (2, 'Quality Control', false, 0);
    INSERT INTO tbl_departments VALUES (3, 'Engineering', false, 0);
    INSERT INTO tbl_departments VALUES (5, 'Quality Assurance', false, 0);
    INSERT INTO tbl_departments VALUES (6, 'Production', false, 2);

    ALTER TABLE ONLY tbl_departments
        ADD CONSTRAINT tbl_departments_pkey PRIMARY KEY ("iID");

SELECT pg_catalog.setval('"tbl_departments_iID_seq"', 1, false);

the pg_dump sets the iID column to integer rather than serial, which disabled the auto-incrementation. The setval is also set to 1 rather than 7 as one would expect.

When I open the front-end application and go to add new department it fails because all I am providing is: name of new department, active/disabled (true/false), ID of parent dept. (0 if no parent).

I am expecting for the new record primary key iID to be created automatically by the DB, which as far as I know is an expected basic feature of any RDBMS.

because the pg_dump converts the serials to integers the auto-incrementation stops.

Charterhouse answered 9/10, 2015 at 8:38 Comment(3)
What is the exact command you use to dump the structure? The file should contain the inserts for the table that is using that sequence, and those inserts should increment the sequence. Btw: you should avoid the use of quoted identifiers they are much more trouble than they are worth it (I also question the use of a tbl prefix - do you prefix all your classes in your programming language with Class as well?)Acme
I added the pg_dump command at the bottom of original commentCharterhouse
The dump file script is building the table first, that sets the sequence to 0, and then does the inserts - but it actually inserts the values for iID. Would that hold the incrementation of sequence?Charterhouse
E
4

There is no reason for concern. The generated SQL file will restore current values of sequences. Open the file with an editor and look for setval. There should be lines like this:

SELECT pg_catalog.setval('test_id_seq', 1234, true);

If you cannot find them it means that INSERT commands set the proper value of a sequence.


As Craig noticed, the current value of the sequence had to be equal to 1 at the time of dump of the original database. You have probably inserted iID values directly, not using default. In that case the sequence is not used.

Therefore I suggest start from the beginning, but in two databases:

  • make an sql dump like in the question,
  • create a new database,
  • run the sql script in the new database,
  • check whether corresponding serial columns have the same declaration in both databases,
  • compare current values of corresponding sequences in both databases.
Erk answered 9/10, 2015 at 9:42 Comment(2)
In edit1 there were no setvals and in edit2 one suddenly appeared? Your question is inconsistent. I would suggest you to reset the test and start from the beginning.Erk
it "suddenly" appear as I was adding information in response to suggestions. I have edited the original to include all parts of dump file that have to do with creation, alteration and data insert for that particular table in order in which they appear.Charterhouse
R
2

the pg_dump sets the iID column to integer rather than serial, which disabled the auto-incrementation.

That's normal. See the manual.

SERIAL is basically just shorthand for CREATE SEQUENCE and then an integer column that makes that sequence its default for nextval('seq_name').

The setval is also set to 1 rather than 7 as one would expect.

I can only explain that one by assuming that the sequence start point is 1 in the DB. Perhaps due to a prior attempt at running DDL that altered it, such as a setval or alter sequence?

setval it to the start point you expect. Then, so long as you don't run other setval commands, alter sequence commands, etc, you'll be fine.

Or maybe the app inserted values directly, without using the sequence?

Riannon answered 9/10, 2015 at 17:49 Comment(0)
O
-1
SELECT setval(pg_get_serial_sequence('public.table', 'id'), max(id)+1) FROM public.table;
Operational answered 24/11, 2021 at 21:37 Comment(1)
Can you offer an explanation? Why is this preferred over e.g. the top-rated answer?Titillate

© 2022 - 2024 — McMap. All rights reserved.