2

In PostgreSQL you can create a temporary table very easily with:

CREATE TEMPORARY TABLE tmp_foo AS
SELECT bar, baz FROM some_table WHERE ...;

Is there any easy way to get a create statement for that table? I can make queries to get information about the table structure (eg in psql I can use \d) but that doesn't give me a creation statement that I can use.

I would like this so that I can materialize queries in one PostgreSQL database, get the table structure of the query, create that temporary table in another, and then use COPY commands to copy data from one to the other before proceeding.

2 Answers 2

2

In general, reconstructing the CREATE TABLE statement gets pretty complicated, if you need to account for column defaults, foreign keys, check constraints, etc.

But the product of a CREATE TABLE AS ... statement won't have any of this, so it's relatively straightforward. Plug your table name into the WHERE clause of this query:

SELECT
  format(
    'CREATE TEMP TABLE %s (%s)',
    attrelid::regclass,
    string_agg(
      format(
        '%I %s',
        attname,
        format_type(atttypid, atttypmod)
      ),
      ','
      ORDER BY attnum
    )
  )
FROM pg_attribute
WHERE
  attrelid = 'tmp_foo'::regclass AND
  attnum > 0 AND
  NOT attisdropped
GROUP BY attrelid

As a side-note, instead of doing this:

CREATE TEMP TABLE tmp_foo AS SELECT ... ;
COPY tmp_foo TO STDOUT;

... you can get the structure of the SELECT result without actually running it, which avoids creating an intermediate copy of the data:

CREATE TEMP TABLE tmp_foo AS SELECT ... WITH NO DATA;
COPY (SELECT ...) TO STDOUT;
Sign up to request clarification or add additional context in comments.

1 Comment

Perfect! It is too bad this isn't a native function.
0

The easiest trick would be to use pg_dump:

$ pg_dump -s -t tmp_foo _dbname_

Of course, this will only work for a non-temporary table. But you could also just create a regular table and do a pipe like pg_dump ... | psql ... or pg_dump ... | pg_restore ... to do your task.

6 Comments

I have done things like that before, but there is a problem if I do not have permissions to create tables. Also it is a code maintenance problem where every time the query changes, the table creation also has to change. (I've seen that screw up too many times.)
Using pg_dump can get you past the query change problem, but not the permission one.
Using pg_dump can't automate the query change problem.
I don't see how it doesn't. It doesn't know anything about the query, it's just fetching a table from database A and writing it to database B.
This suggests to me that you have per-user tables, which is a normalization smell. Probably you should have one big table that contains every user's stuff and have a system user do the moving around, then use views or procedures to confine access to that table to matching users.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.