3

I plan of using auto increments as a primary key on one of my table.

I need to store data related to each row in an other storage system and I plan to use each primary key id as the key for the data.

Is it guaranteed that even after the restoration of a pg_dump, each row will still have the same id?

user312016
  • 133
  • 1
  • 5
  • 2
    Unless you do something very esoteric (such as having an enabled on insert trigger that changes it while restoring your data), the answer is YES. PostgreSQL is not working like MS-Access WRT to autoincrement, which is called serial – joanolo Jan 16 '17 at 21:00
  • @joanolo AFAIK, triggers don't interfere with pg_restore. They're applied after the dataset. – Evan Carroll Jan 17 '17 at 03:29
  • @EvanCarroll: if you choose the right (should I say wrong?) options, they do. Or, at least, they did. When you restore a full database, you normally don't have problems, types, functions, table type definitions, data, constraints, indexes and triggers go in the optimal order. If you restore just the data of a table (or schema), and forget to disable triggers... things may go wrong. – joanolo Jan 17 '17 at 07:59

1 Answers1

4

A quick overview:

  • PostgreSQL does not have AUTO INCREMENTS. There is no special type.
  • In order to set this up PostgreSQL uses the standard IDENTITY COLUMNS which associates a SEQUENCE with the int type.

Let's create a table,

CREATE TABLE foo (
  foo_id int PRIMARY KEY,
  bar    int GENERATED BY DEFAULT AS IDENTITY
);

When you pg_dump that table with an IDENTITY COLUMN you'll see this,

CREATE TABLE public.foo (
    foo_id integer NOT NULL,
    bar integer
);

That's because the type is simply int type. Now, when you load you'll see right after the table this,

ALTER TABLE public.foo ALTER COLUMN foo_id ADD GENERATED BY DEFAULT AS IDENTITY (
    SEQUENCE NAME public.foo_foo_id_seq
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1
);

This tells the pg_restore the state associated with the sequence the IDENTITY COLUMN was using.

# \d foo
                             Table "public.foo"
 Column |  Type   | Collation | Nullable |             Default              
--------+---------+-----------+----------+----------------------------------
 foo_id | integer |           | not null | generated by default as identity
 bar    | integer |           |          |

Then the data is loaded and when it's loaded all of the values of that sequence for each row are specified in the load -- they maintain the old values from the dump.*

Note that the PostgreSQL implementation of an IDENTITY COLUMN which is more less sugar for SEQUENCE does not ensure a gaplessness.

Footnotes

  • I've left off the permission stuff for brevity.
  • *I've removed all of the stuff about serial, bigserial and what serial was and how it worked because moving forward it should not be a thing. PostgreSQL users should be using IDENTITY COLUMNS in all circumstances.
Evan Carroll
  • 63,051
  • 46
  • 242
  • 479