Creating a copy of a database in PostgreSQL - postgresql

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

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();

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.

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

In production environment, where the original database is under traffic, I'm simply using:
pg_dump production-db | psql test-db

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.

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

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:
Right click the source database, Backup... and dump to a file.
Right click, New Object, New Database... and name the destination.
Right click the new database, Restore... and select your file.

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):
nohup pg_dump exampledb > example-01.sql
createdb -O postgres exampledbclone_01
my user is "postgres"
nohup psql exampledbclone_01 < example-01.sql

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.

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"
2. Give the file a name.
Like test12345. Click backup. This creates a binary file dump, it's not in a .sql format
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
4. Find the location of downloaded file
In this case, it's /users/vincenttang
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"
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:
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
8. Restore said file
You'll see this page again, with the location of the file selected. Go ahead and restore it
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"
Execute this code block:
DROP SCHEMA public CASCADE; CREATE SCHEMA public;
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

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.

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"

PostgreSQL 9.1.2:
$ CREATEDB new_db_name -T orig_db_name -O db_user;

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

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"

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.

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.

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”

Open the Main Window in pgAdmin and then open another Query Tools Window
In the main windows in pgAdmin,
Disconnect the "templated" database that you want to use as a template.
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;

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.

CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;
If you have using Ubuntu.
1 way
createdb -O Owner -T old_db_name new_db_name
2 way
createdb test_copy
pg_dump old_db_name | psql test_copy

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

Related

How to restore database from .pg_dump file using pgAdmin

I was given a mydb.pg_dump file. I have created a new database test1 with pgAdmin. When I click right on the database and select Restore..., I can select my file after selecting "All files". But when I attempt to restore the database I immediately obtain this error:
pg_restore: error: input file appears to be a text format dump. Please
use psql.
Can I use pgAdmin to restore a .pg_dump file? How?
You cannot use pgAdmin for that, because in a plain-text dump COPY statements are mixed with COPY data.
You need psql for that, which fortunately is already installed on your machine:
psql -d mydb -U postgres -f mydb.pg_dump

PostgreSQL: import/restore database dump (pg_dump version 9.6.5) on Windows

I am a newbie and I have a postgresql large dump of type .sql and i want to import it. I am on Windows 10 and haven't been able to find solution.
I tried to restore using pgAdmin3 but it doesn't show .sql file while restoring. I also found few commands and tried them but nothing seems to work.
I also tried loading the datasource in IntelliJ DataGrid but it doesn't show the correct driver during the loading settings.
Can someone help?
First, figure out if the dump was created with pg_dumpall or pg_dump.
Dumps from pg_dumpall start with:
--
-- PostgreSQL database cluster dump
--
If the dump was created with pg_dump, find out if the -C option was used.
If yes, the dump will contain a line with a CREATE DATABASE statement.
To restore, use psql from the DOS box. I assume that psql is on your PATH.
A dump from pg_dumpall or pg_dump -C is restored with
psql -U postgres -d postgres -f dumpfile.sql
A dump from pg_dump without -C is restored with
psql -U postgres -d mydatabase -f dumpfile.sql
where mydatabase should be replaced with the name of the target database into which the dump should be restored.

psql.exe postgresql create database via CMD

I search to create a database via CMD, i success to create it using this command:
C:\>"C:\Program Files\PostgreSQL\9.3\bin\psql.exe" -U postgres template1
So when i excute this command i can Create my database like this:
template1=# CREATE DATABASE d_base;
My objectif is to create this database with just one line:
like this:
C:\>"C:\Program Files\PostgreSQL\9.3\bin\psql.exe" -U postgres template1 "CREATE DATABASE T;"
But this not work with me, it gave me this error:
i can solve this problem with creating a .bat Script but my objectif is to use just one line,
Is there any solution for that.
Thank you.
You get that error because template1 is not the last argument. You can use -d to specify the database.
Use the database postgres instead of template1.
Try this:
"C:\Program Files\PostgreSQL\9.3\bin\psql.exe" -U postgres -d postgres -c "CREATE DATABASE t"
https://www.postgresql.org/docs/9.3/static/app-psql.html
see --command=command section

I want to export a script for my database in postgres

I've created a database in pgAdmin, in which I've 1 public schema and 4 custom schema's. These schema contains several functions, sequences and Tables. Now I want to export a script that can create same database with the same structure without any data. Please help me with this....
You are looking for pg_dump with the (default) plain format.
If you can access to the command line, type this
pg_dump --create --clean --schema-only -U your_user -d db_name > file_name.sql
Then in the server you need to create same database run this
psql -U db_user -d db_name < file_name.sql
--clean option tries to drop all objects before creating them.
--create Begin the output with a command to create the database itself and reconnect to the created database.

I want to restore the database with a different schema

I have taken a dump of a database named temp1, by using the follwing command
$ pg_dump -i -h localhost -U postgres -F c -b -v -f pub.backup temp1
Now I want to restore the dump in a different database called "db_temp" , but in that I just want that all the tables should be created in a "temp_schema" ( not the default schema which is in the fms temp1 database ) which is in the "db_temp" database.
Is there any way to do this using pg_restore command?
Any other method also be appreciated!
A quick and dirty way:
1) rename default schema:
alter schema public rename to public_save;
2) create new schema as default schema:
create schema public;
3) restore data
pg_restore -f pub.backup db_temp [and whatever other options]
4) rename schemas according to need:
alter schema public rename to temp_schema;
alter schema public_save rename to public;
There is a simple solution:
Create your backup dump in plain SQL format (format "p" using the parameter --format=p or -F p)
Edit your pub.backup.sql dump with your favorite editor and add the following two lines at the top of your file:
create schema myschema;
SET search_path TO myschema;
Now you can restore your backup dump with the command
psql -f pub.backup.sql
The set search_path to <schema> command will set myschema as the default, so that new tables and other objects are created in this schema, independently of the "default" schema where they lived before.
There's no way in pg_restore itself. What you can do is use pg_restore to generate SQL output, and then send this through for example a sed script to change it. You need to be careful about how you write that sed script though, so it doesn't match and change things inside your data.
Probably the easiest method would be to simply rename the schema after restore, ie with the following SQL:
ALTER SCHEMA my_schema RENAME TO temp_schema
I believe that because you're using the compressed archive format for the output of pg_dump you can't alter it before restoring. The option would be to use the default output and do a search and replace on the schema name, but that would be risky and could perhaps cause data to be corrupted if you were not careful.
If you only have a few tables then you can restore one table at a time, pg_restore accepts -d database when you specify -t tablename. Of course, you'll have to set up the schema before restoring the tables and then sort out the indexes and constraints when you're done restoring the tables.
Alternatively, set up another server on a different port, restore using the new PostgreSQL server, rename the schema, dump it, and restore into your original database. This is a bit of a kludge of course but it will get the job done.
If you're adventurous you might be able to change the database name in the dump file using a hex editor. I think it is only mentioned in one place in the dump and as long as the new and old database names are the same it should work. YMMV, don't do anything like this in a production environment, don't blame me if this blows up and levels your home town, and all the rest of the usual disclaimers.
Rename the schema in a temporary database.
Export the schema:
pg_dump --schema-only --schema=prod > prod.sql
Create a new database. Restore the export:
psql -f prod.sql
ALTER SCHEMA prod RENAME TO somethingelse;
pg_dump --schema-only --schema=somethingelse > somethingelse.sql
(delete the database)
For the data you can just modify the set search_path at the top.
As noted, there's no direct support in pg_dump, psql or pg_restore to change the schema name during a dump/restore process. But it's fairly straightforward to export using "plain" format then modify the .sql file. This Bash script does the basics:
rename_schema () {
# Change search path so by default everything will go into the specified schema
perl -pi -e "s/SET search_path = $2, pg_catalog/SET search_path = $3, pg_catalog, $2;/" "$1"
# Change 'ALTER FUNCTION foo.' to 'ALTER FUNCTION bar.'
perl -pi -e 's/^([A-Z]+ [A-Z]+) '$2'\./$1 '$3'./' "$1"
# Change the final GRANT ALL ON SCHEMA foo TO PUBLIC
perl -pi -e 's/SCHEMA '$2'/SCHEMA '$3'/' "$1"
}
Usage:
pg_dump --format plain --schema=foo --file dump.sql MYDB
rename_schema dump.sql foo bar
psql -d MYDB -c 'CREATE SCHEMA bar;'
psql -d MYDB -f dumpsql
The question is pretty old, but maybe can help some one.
Streaming the output of pg_restore to sed and replace the schema name in order to import the dump to a different schema.
Something like:
pg_restore ${dumpfile} | \
sed -e "s/OWNER TO ${source_owner}/OWNER TO ${target_owner}/" \
-e "s/${source_schema}/${target_schema}/" | \
psql -h ${pgserver} -d ${dbname} -U ${pguser}