31

How to create a temporary table, if it does not already exist, and add the selected rows to it?

Braiam
  • 1
  • 11
  • 47
  • 78
inf3rno
  • 24,976
  • 11
  • 115
  • 197
  • Can you upgrade to 9.1 or later? Those versions support `create table .. if not exists` –  Sep 17 '13 at 14:57
  • 2
    You know that 8.4 will be de-supported mid of next year? You should plan you upgrade anyway: http://www.postgresql.org/support/versioning/ –  Sep 17 '13 at 16:28
  • Ofc I know, I pay for hosting, so I suppose they will upgrade the version asap. Does not depend on me... – inf3rno Sep 17 '13 at 18:31

1 Answers1

69

CREATE TABLE AS

is the simplest and fastest way:

CREATE TEMP TABLE tbl AS
SELECT * FROM tbl WHERE ... ;

Do not use SELECT INTO for this purpose. See:

Not sure whether table already exists

CREATE TABLE IF NOT EXISTS ... was added with Postgres 9.1. For older versions, see:

Then:

INSERT INTO tbl (col1, col2, ...)
SELECT col1, col2, ...

Chances are, something is going wrong in your code if the temp table already exists. Make sure you don't duplicate data in the table or something. Or consider the following paragraph ...

Unique names

Temporary tables are only visible within your current session (not to be confused with transaction!). So the table name cannot conflict with other sessions. If you need unique names within your session, you could use dynamic SQL and utilize a SEQUENCE:

Create once:

CREATE SEQUENCE tablename_helper_seq;

You could use a DO statement (or a plpgsql function):

DO
$do$
BEGIN
   EXECUTE
   'CREATE TEMP TABLE tbl' || nextval('tablename_helper_seq'::regclass) || ' AS
    SELECT * FROM tbl WHERE ... ';

   RAISE NOTICE 'Temporary table created: "tbl%"' || ', lastval();
END
$do$;

lastval() and currval(regclass) are instrumental to return the dynamically created table name.

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
  • 4
    Small addition that, if you need to specify transactional behavior, you do it before the "as" part: **create temp table tbl ON COMMIT DROP as** [your mighty select goes here] – Anatoly Alekseev Sep 08 '21 at 07:06