932

What's the correct way to copy entire database (its structure and data) to a new one in pgAdmin?

1
  • 7
    Asking questions about PostgreSQL is on-topic, and does not fall into the category of "general computing hardware and software". PostgreSQL is not software that you would expect an average computer user to use, but it is software that programmers use and need to be able to run queries on.
    – Flimm
    Commented Apr 28, 2021 at 9:01

22 Answers 22

1430

Postgres allows the use of any existing database on the server as a template when creating a new database. I'm not sure whether pgAdmin gives you the option on the create database dialog but you should be able to execute the following in a query window if it doesn't:

CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;

Still, you may get:

ERROR:  source database "originaldb" is being accessed by other users

To disconnect all other users from the database, you can use this query:

SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity 
WHERE pg_stat_activity.datname = 'originaldb' AND pid <> pg_backend_pid();
18
  • 83
    Note that originaldb needs to be idle (no write transactions) for this to work.
    – synecdoche
    Commented May 19, 2010 at 23:51
  • 69
    in pgAdmin3, in the Object browser (left) pane, I can select Servers -> (my server) -> Databases, right-click Databases, and select "New Database". One of the options is the template, and the SQL used to create the database is equivalent. It is so much faster than a dump / restore on the same server.
    – jwhitlock
    Commented Jun 17, 2011 at 15:19
  • 29
    I know this is an old Q/A, but I feel it needs clarification: When @synecdoche says that originaldb must be idle, that means no write possibility at all. "Copying" a database in this fashion does not lock originaldb. PostgreSQL only prevents starting the copy if there are others accessing originaldb--not after the copy starts, so it is possible that another connection could modify the database while the "copy" is occurring. IMHO, this may be the easiest answer, but the "best" would be to use dump/restore.
    – Josh
    Commented Jan 25, 2012 at 15:20
  • 10
    I just saw this. @Josh: while the originaldb is being copied by create database with template, postgresql does not allow creating a new connection to it, so no changes are possible.
    – ceteras
    Commented Nov 14, 2012 at 17:15
  • 7
    Note that if you're using pgAdmin and executing CREATE DATABASE ... TEMPLATE xxx from a SQL command window, you must disconnect from the database in the main pgAdmin window or you'll get the error about users connected to the database.
    – Jack R-G
    Commented Sep 18, 2014 at 19:18
328

A command-line version of Bell's answer:

createdb -O ownername -T originaldb newdb

This should be run under the privileges of the database master, usually postgres.

2
  • 7
    This is a nice command BUT you will get createdb: database creation failed: ERROR: source database "conf" is being accessed by other users if you try to do it on a production database and as expected you do not want to shut it down to create a copy.
    – sorin
    Commented Apr 5, 2012 at 12:28
  • 9
    Yes, the same caveats apply to this command, as to explicit CREATE DATABASE invocation. Like the comments for Bell's answer above say, the database should be idle.
    – zbyszek
    Commented Apr 13, 2012 at 15:50
126

To clone an existing database with postgres you can do that

/* KILL ALL EXISTING CONNECTION FROM ORIGINAL DB (sourcedb)*/
SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity 
WHERE pg_stat_activity.datname = 'SOURCE_DB' AND pid <> pg_backend_pid();

/* CLONE DATABASE TO NEW ONE(TARGET_DB) */
CREATE DATABASE TARGET_DB WITH TEMPLATE SOURCE_DB OWNER USER_DB;

IT will kill all the connection to the source db avoiding the error

ERROR:  source database "SOURCE_DB" is being accessed by other users
2
  • 8
    +1 for mentioning a script solution to avoid the access error
    – bully
    Commented Jul 8, 2014 at 12:35
  • 17
    On Postgres 9.2 I have to replace procpid with pid for this to work Commented Sep 10, 2014 at 10:14
125

In production environment, where the original database is under traffic, I'm simply using:

pg_dump production-db | psql test-db
10
  • 13
    One issue I've found with this method is that pg_dump will hold open its transaction until the restore into the new database is complete, even if pg_dump has actually finished its dump. This can cause locking issues in some cases (for example, if a DDL statement is run on the source DB). Commented Mar 4, 2015 at 17:17
  • 4
    Plus one for not using temporary intermediate files.
    – Ardee Aram
    Commented Jul 6, 2015 at 4:27
  • It was also my solution. Yesterday it worked, now random unique constrain are violated. Note: I drop all table to receiver db.
    – gunzapper
    Commented Apr 1, 2016 at 10:45
  • 2
    @AlexanderMills pg_dump -s? postgresql.org/docs/current/static/app-pgdump.html
    – Tregoreg
    Commented Oct 24, 2016 at 19:15
  • 8
    This assume that test-db exists. Otherwise, create the new db with $ createdb newdb
    – SamGoody
    Commented Aug 31, 2017 at 9:53
55

Don't know about pgAdmin, but pgdump gives you a dump of the database in SQL. You only need to create a database by the same name and do

psql mydatabase < my dump

to restore all of the tables and their data and all access privileges.

3
  • Thanks, I needed to create a dump from another server, and it seems this helps: postgresql.org/docs/8.3/interactive/…
    – egaga
    Commented May 18, 2009 at 11:33
  • 23
    You can even do pg_dump -U postgres sourcedb | psql -U postgres newdb although the efficiency of this technique may be questionable (since you probably end up context switching between reads and writes) Commented Jun 7, 2010 at 17:19
  • 1
    You can even get your dump from a remote machine via ssh: ssh dbserver pg_dump DBNAME | psql NEWDB ... or pg_dump DBNAME | ssh otherserver pgsql NEWDB ... Permissions and authentication of course need to be handled however you want to handle them.
    – ghoti
    Commented Aug 15, 2012 at 15:52
37

First, sudo as the database user:

sudo su postgres

Go to PostgreSQL command line:

psql

Create the new database, give the rights and exit:

CREATE DATABASE new_database_name;
GRANT ALL PRIVILEGES ON DATABASE new_database_name TO my_user;
\d

Copy structure and data from the old database to the new one:

pg_dump old_database_name | psql new_database_name
5
  • how to make sure that everyhing is OK even some errors (network issue) happened? How to check whether the two databases are the same after migration?
    – BAE
    Commented Jan 14, 2016 at 18:18
  • Errors should be displayed in terminal whenever encountered. The two databases should be the same after the operation. However, I don't know how to check this... Commented Jan 15, 2016 at 20:24
  • 3
    Works like a charm, I did it while the database was in production.
    – BioRod
    Commented Nov 10, 2016 at 16:40
  • This appears to work well; however, the two databases have different disc size via \l+ . Why the size difference?
    – kosgeinsky
    Commented Feb 3, 2019 at 7:11
  • 1
    @kosgeinsky this has been extensively answered here: dba.stackexchange.com/a/102089/39386 Commented Feb 4, 2019 at 10:33
34

In pgAdmin you can make a backup from your original database, and then just create a new database and restore from the backup just created:

  1. Right click the source database, Backup... and dump to a file.
  2. Right click, New Object, New Database... and name the destination.
  3. Right click the new database, Restore... and select your file.
1
  • I have related tables via foreign keys and this worked just fine. Commented Mar 18, 2018 at 15:11
30

Copying an "under load" db

I pieced this approach together with the examples from above. I'm working on an "under load" server and got the error when I attempted the approach from @zbyszek. I also was after a "command line only" solution.

createdb: database creation failed: ERROR: source database "exampledb" is being accessed by other users.

Here's what worked for me (Commands prepended with nohup to move output into a file and protect from a server disconnect):

  1. nohup pg_dump exampledb > example-01.sql
  2. createdb -O postgres exampledbclone_01

    my user is "postgres"

  3. nohup psql exampledbclone_01 < example-01.sql
28

Here's the whole process of creating a copying over a database using only pgadmin4 GUI (via backup and restore)

Postgres comes with Pgadmin4. If you use macOS you can press CMD+SPACE and type pgadmin4 to run it. This will open up a browser tab in chrome.


Steps for copying

1. Create the backup

Do this by rightclicking the database -> "backup"

enter image description here

2. Give the file a name.

Like test12345. Click backup. This creates a binary file dump, it's not in a .sql format

enter image description here

3. See where it downloaded

There should be a popup at the bottomright of your screen. Click the "more details" page to see where your backup downloaded to

enter image description here

4. Find the location of downloaded file

In this case, it's /users/vincenttang

enter image description here

5. Restore the backup from pgadmin

Assuming you did steps 1 to 4 correctly, you'll have a restore binary file. There might come a time your coworker wants to use your restore file on their local machine. Have said person go to pgadmin and restore

Do this by rightclicking the database -> "restore"

enter image description here

6. Select file finder

Make sure to select the file location manually, DO NOT drag and drop a file onto the uploader fields in pgadmin. Because you will run into error permissions. Instead, find the file you just created:

enter image description here

7. Find said file

You might have to change the filter at bottomright to "All files". Find the file thereafter, from step 4. Now hit the bottomright "Select" button to confirm

enter image description here

8. Restore said file

You'll see this page again, with the location of the file selected. Go ahead and restore it

enter image description here

9. Success

If all is good, the bottom right should popup an indicator showing a successful restore. You can navigate over to your tables to see if the data has been restored propery on each table.

10. If it wasn't successful:

Should step 9 fail, try deleting your old public schema on your database. Go to "Query Tool"

enter image description here

Execute this code block:

DROP SCHEMA public CASCADE; CREATE SCHEMA public;

enter image description here

Now try steps 5 to 9 again, it should work out

EDIT - Some additional notes. Update PGADMIN4 if you are getting an error during upload with something along the lines of "archiver header 1.14 unsupported version" during restore

24

What's the correct way to copy entire database (its structure and data) to a new one in pgAdmin?

Answer:

CREATE DATABASE newdb WITH TEMPLATE originaldb;

Tried and tested.

3
  • 4
    This requires originaldb to not be in use. Isomorph's method does not.
    – Bradley
    Commented Jan 16, 2012 at 19:50
  • 3
    The same answer was provided nearly three years prior to yours
    – Jason S
    Commented Aug 15, 2016 at 22:09
  • 1
    Upvoted because unlike the top answer, this answer at least specifies that the command will copy structure AND data, which was what I wanted to confirm happens.
    – Emmanuel
    Commented Dec 23, 2020 at 5:36
15

From the documentation, using createdb or CREATE DATABASE with templates is not encouraged:

Although it is possible to copy a database other than template1 by specifying its name as the template, this is not (yet) intended as a general-purpose “COPY DATABASE” facility. The principal limitation is that no other sessions can be connected to the template database while it is being copied. CREATE DATABASE will fail if any other connection exists when it starts; otherwise, new connections to the template database are locked out until CREATE DATABASE completes.

pg_dump or pg_dumpall is a good way to go for copying database AND ALL THE DATA. If you are using a GUI like pgAdmin, these commands are called behind the scenes when you execute a backup command. Copying to a new database is done in two phases: Backup and Restore

pg_dumpall saves all of the databases on the PostgreSQL cluster. The disadvantage to this approach is that you end up with a potentially very large text file full of SQL required to create the database and populate the data. The advantage of this approach is that you get all of the roles (permissions) for the cluster for free. To dump all databases do this from the superuser account

pg_dumpall > db.out

and to restore

psql -f db.out postgres

pg_dump has some compression options that give you much smaller files. I have a production database I backup twice a day with a cron job using

pg_dump --create --format=custom --compress=5 --file=db.dump mydatabase

where compress is the compression level (0 to 9) and create tells pg_dump to add commands to create the database. Restore (or move to new cluster) by using

pg_restore -d newdb db.dump

where newdb is the name of the database you want to use.

Other things to think about

PostgreSQL uses ROLES for managing permissions. These are not copied by pg_dump. Also, we have not dealt with the settings in postgresql.conf and pg_hba.conf (if you're moving the database to another server). You'll have to figure out the conf settings on your own. But there is a trick I just discovered for backing up roles. Roles are managed at the cluster level and you can ask pg_dumpall to backup just the roles with the --roles-only command line switch.

9

For those still interested, I have come up with a bash script that does (more or less) what the author wanted. I had to make a daily business database copy on a production system, this script seems to do the trick. Remember to change the database name/user/pw values.

#!/bin/bash

if [ 1 -ne $# ]
then
  echo "Usage `basename $0` {tar.gz database file}"
  exit 65;
fi

if [ -f "$1" ]
then
  EXTRACTED=`tar -xzvf $1`
  echo "using database archive: $EXTRACTED";
else
  echo "file $1 does not exist"
  exit 1
fi


PGUSER=dbuser
PGPASSWORD=dbpw
export PGUSER PGPASSWORD

datestr=`date +%Y%m%d`


dbname="dbcpy_$datestr"
createdbcmd="CREATE DATABASE $dbname WITH OWNER = postgres ENCODING = 'UTF8' TABLESPACE = pg_default LC_COLLATE = 'en_US.UTF-8' LC_CTYPE = 'en_US.UTF-8' CONNECTION LIMIT = -1;"
dropdbcmp="DROP DATABASE $dbname"

echo "creating database $dbname"
psql -c "$createdbcmd"

rc=$?
if [[ $rc != 0 ]] ; then
  rm -rf "$EXTRACTED"
  echo "error occured while creating database $dbname ($rc)"
  exit $rc
fi


echo "loading data into database"
psql $dbname < $EXTRACTED > /dev/null

rc=$?

rm -rf "$EXTRACTED"

if [[ $rc != 0 ]] ; then
  psql -c "$dropdbcmd"
  echo "error occured while loading data to database $dbname ($rc)"
  exit $rc
fi


echo "finished OK"
8

PostgreSQL 9.1.2:

$ CREATEDB new_db_name -T orig_db_name -O db_user;
2
  • 3
    This is probably implemented as CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser; and as a result requires that the original database must be idle (no connections with write access) and any new connections to original database are prevented while the copying is in process. If you're happy with that, this works. Commented Mar 6, 2013 at 9:09
  • Nice detail. Thank you!
    – Arta
    Commented Aug 25, 2015 at 17:27
6

To create database dump

cd /var/lib/pgsql/
pg_dump database_name> database_name.out

To resote database dump

psql -d template1
CREATE DATABASE database_name WITH  ENCODING 'UTF8' LC_CTYPE 'en_US.UTF-8' LC_COLLATE 'en_US.UTF-8' TEMPLATE template0;
CREATE USER  role_name WITH PASSWORD 'password';
ALTER DATABASE database_name OWNER TO role_name;
ALTER USER role_name CREATEDB;
GRANT ALL PRIVILEGES ON DATABASE database_name to role_name;


CTR+D(logout from pgsql console)
cd /var/lib/pgsql/

psql -d database_name -f database_name.out
0
5

You can use CREATE ... WITH TEMPLATE to make copies, but it is not general purpose and not recommended as a general solution. The important bit from the docs is:

The principal limitation is that no other sessions can be connected to the template database while it is being copied.

CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;

If you have using Ubuntu. 1st way createdb -O Owner -T old_db_name new_db_name

2nd way

createdb test_copy
pg_dump old_db_name | psql test_copy
1
4

If the database has open connections, this script may help. I use this to create a test database from a backup of the live-production database every night. This assumes that you have an .SQL backup file from the production db (I do this within webmin).

#!/bin/sh

dbname="desired_db_name_of_test_enviroment"
username="user_name"
fname="/path to /ExistingBackupFileOfLive.sql"

dropdbcmp="DROP DATABASE $dbname"
createdbcmd="CREATE DATABASE $dbname WITH OWNER = $username "

export PGPASSWORD=MyPassword



echo "**********"
echo "** Dropping $dbname"
psql -d postgres -h localhost -U "$username" -c "$dropdbcmp"

echo "**********"
echo "** Creating database $dbname"
psql -d postgres -h localhost -U "$username" -c "$createdbcmd"

echo "**********"
echo "** Loading data into database"
psql -d postgres -h localhost -U "$username" -d "$dbname" -a -f "$fname"
3

Using pgAdmin, disconnect the database that you want to use as a template. Then you select it as the template to create the new database, this avoids getting the already in use error.

3

pgAdmin4:

1.Select DB you want to copy and disconnect it

Rightclick "Disconnect DB"

2.Create a new db next to the old one:

  • Give it a name.
  • In the "definition" tab select the first table as an Template (dropdown menu)

Hit create and just left click on the new db to reconnect.

2

New versions of pgAdmin (definitely 4.30) support creating new databases from template. All you need to populate are new database name and existing template database.

enter image description here

2
  • He is asking about copying a database, not creating one... Commented Jan 21, 2022 at 16:50
  • 2
    @FelipeCandalCampos In postgres CREATE WITH TEMPLATE means to create a copy. I have just gave a hint how to do that conveniently using pgAdmin. I found it useful.
    – Kuba D
    Commented Jan 22, 2022 at 14:55
1

If you want to copy whole schema you can make a pg_dump with following command:

pg_dump -h database.host.com -d database_name -n schema_name -U database_user --password

And when you want to import that dump, you can use:

psql "host=database.host.com user=database_user password=database_password dbname=database_name options=--search_path=schema_name" -f sql_dump_to_import.sql

More info about connection strings: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING

Or then just combining it in one liner:

pg_dump -h database.host.com -d postgres -n schema_name -U database_user --password | psql "host=database.host.com user=database_user password=database_password dbname=database_name options=--search_path=schema_name”
1
  1. Open the Main Window in pgAdmin and then open another Query Tools Window
  2. In the main windows in pgAdmin,

Disconnect the "templated" database that you want to use as a template.

  1. Goto the Query Tools Window

Run 2 queries as below

SELECT pg_terminate_backend(pg_stat_activity.pid) 
    FROM pg_stat_activity 
    WHERE pg_stat_activity.datname = 'TemplateDB' AND pid <> pg_backend_pid(); 

(The above SQL statement will terminate all active sessions with TemplateDB and then you can now select it as the template to create the new TargetDB database, this avoids getting the already in use error.)

CREATE DATABASE 'TargetDB'
  WITH TEMPLATE='TemplateDB'
       CONNECTION LIMIT=-1;
-4

Try this:

CREATE DATABASE newdb WITH ENCODING='UTF8' OWNER=owner TEMPLATE=templatedb LC_COLLATE='en_US.UTF-8' LC_CTYPE='en_US.UTF-8' CONNECTION LIMIT=-1;

gl XD

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.