DISCLAIMER: This question is similar to the stack overflow question here, but none of those answers work for my problem, as I will explain later.
I\'m t
The closest "miracle command" is something like
pg_dump -t tablename | sed -r 's/\btablename\b/tablename_copy/' | psql -f -
In particular, this takes care of creating the indexes after loading the table data.
But that doesn't reset the sequences; you will have to script that yourself.
To copy a table completely, including both table structure and data, you use the following statement:
CREATE TABLE new_table AS
TABLE existing_table;
To copy a table structure without data, you add the WITH NO DATA clause to the CREATE TABLE statement as follows:
CREATE TABLE new_table AS
TABLE existing_table
WITH NO DATA;
To copy a table with partial data from an existing table, you use the following statement:
CREATE TABLE new_table AS
SELECT
*
FROM
existing_table
WHERE
condition;
Apparently you want to "rebuild" a table. If you only want to rebuild a table, not copy it, then you should use CLUSTER instead.
SELECT count(*) FROM table; -- make a seq scan to make sure the table is at least
-- decently cached
CLUSTER someindex ON table;
You get to choose the index, try to pick one that suits your queries. You can always use the primary key if no other index is suitable.
If your table is too large to be cached, CLUSTER can be slow though.
create table newTableName (like oldTableName including indexes); insert into newTableName select * from oldTableName
This worked for me 9.3
WARNING:
All the answers which use pg_dump and any sort of regular expression to replace the name of the source table are really dangerous. What if your data contains the substring that you are trying to replace? You will end up changing your data!
I propose a two-pass solution:
Here's an example written in Ruby:
ruby -pe 'gsub(/(members?)/, "\\1_copy_20130320") unless $_ =~ /^\d+\t.*(?:t|f)$/' < members-production-20130320.sql > copy_members_table-20130320.sql
In the above I am trying to copy "members" table into "members_copy_20130320". My data-specific regexp is /^\d+\t.*(?:t|f)$/
The above type of solution works for me. Caveat emptor...
edit:
OK, here's another way in pseudo-shell syntax for the regexp-averse people:
psql -f mytable_copy_schema.sql mydb
pg_dump -a -t mytable mydb > mytable_data.sql
The create table as
feature in PostgreSQL may now be the answer the OP was looking for.
https://www.postgresql.org/docs/9.5/static/sql-createtableas.html
create table my_table_copy as
select * from my_table
This will create an identical table with the data.
Adding with no data
will copy the schema without the data.
create table my_table_copy as
select * from my_table
with no data
This will create the table with all the data, but without indexes and triggers etc.
create table my_table_copy (like my_table including all)
The create table like syntax will include all triggers, indexes, constraints, etc. But not include data.