Cannot restore Postgresql databases got "database already exists" error - postgresql

I have take backup by pg_dumpall > test.out
and test.out successfully generated, hence backup completed.
I have used command psql -f test.out postgres for restore
But got following errors with restoring backup:
databases already exists
relation "products" already exists
duplicate key value violates unique constraint "products_pkey"
I actually want to replace the data in the existing db with backup. How to do that?

The problem is that the database you're trying to restore already exists.
You can run a DROP DATABASE database_name command that will delete your existing database and then you can run your test.out file.
Or you can run pgdumpall --clean > test.out and then run the resulting file. The clean flag will make the resulting files have the DROP DATABASE command in them.

Do you use the bellow command ?
psql -h localhost -U [login role] database_name -f /home/database.backup

I think a flow like this might help, because we don't want drop the database each time we call the backup file.
First, we need to create a backup file using the --format=custom [-Fc] to restore it using pg_restore. We can use a connection string postgresql://<user>:<pass>#localhost:5432/<dbname> and replace <user>, <pass>, and <dbname> with your information.
pg_dump -v -Fc \
postgresql://<user>:<pass>#localhost:5432/<dbname> \
> db-20211122-163508.sql
To restore we will call it using --clean [-c] and --create [-C] to drop the database before restoring. Replace <user>, <host>, <port>, and <dbname> with your information.
pg_restore -vcC \
-U <user> \
-h <host> \
-p <port> \
-d <dbname> \
< db-20211122-163508.sql
This way you don't need to use clean when you create the backup file.

Related

Can I drop & create db while executing pg_restore command?

I am trying to execute the following command to restore db in a Docker container:
cmd /c "docker exec -i database-container pg_restore -C -U postgres -d employee -v < C:\\backup\\employee.tar"
But it throws: "pg_restore: error: connection to database "employee" failed: FATAL: database "employee" does not exist" (If I create an empty database with the same name, it is created without any problem).
The reason may be:
When this option is used, the database named with -d is used only to issue the initial DROP DATABASE and CREATE DATABASE commands. All data is restored into the database name that appears in the archive.
So, is it possible to restore db using the same pg_restore command? Or should I modify it by adding drop and create commands to fix the problem?
Finally I concluded to drop and create db before restore. If you have a better solution you are welcome and I will give a try.
docker exec database-container bash -c "dropdb -U postgres employee"
docker exec database-container bash -c "createdb -U postgres employee"
cmd /c "docker exec -i database-container pg_restore -C -U postgres -d employee -v
< C:\\backup\\employee.tar"
You can let pg_restore drop and recreate the database before restoring your backup by providing both parameters --create --clean together.
--create
Create the database before restoring into it. If --clean is also specified, drop and recreate the target database before connecting to it.
See https://www.postgresql.org/docs/12/app-pgrestore.html

Postgresql - backup restore on different owner?

My question is similar to this I even vote up it, but unfortunately in my case I have text dump and I can not restore using pg_restore =(
zcat /home/kes/work/projects/bennet/db/bennet.sql.gz | \
pg_restore -h 127.0.0.1 -p 5432 -U bennet --no-owner --role=bennet -d bennet
pg_restore: error: input file appears to be a text format dump. Please use psql.
But psql has no role and no-owner options
Is there a way to restore text dump on different owner?
No. You have two options:
Manually edit the SQL script. This is cumbersom and error-prone.
Restore the complete dump to a new, empty scratch database using psql and dump that with --role and --no-owner as you need.

PostgreSQL pg_basebackup missing toc.dat header file

I'm using the following command to backup my database (PostgreSQL 11.8):
pg_basebackup -D "C:\\temp" -F tar -X f -z -P -U myUser
And the following to restore:
I manually unpack the base.tar.gz => base.tar
pg_restore -h localhost -W -U myUser -c -C -d myDatabase -F tar -v "C:\\temp\\base.tar"
This results in the following error:
pg_restore: [tar archiver] could not find header for file "toc.dat" in tar archive
What am I doing wrong?
Also, I tried different versions of the restore (only data, etc.) but of course the missing header file issue persists.
Thanks for your help!
You cannot use pg_basebackup and pg_restore together:
pg_basebackup is a physical backup tool
pg_restore can only be used with a logical backup created by pg_dump.
There is no single PostgreSQL command to restore a backup created with pg_basebackup.
To restore a physical backup see https://www.postgresql.org/docs/12/continuous-archiving.html#BACKUP-PITR-RECOVERY

pg_restore ERROR: “Relation does not exist” and creating new database

I have made a backup of my specific tables that I want to restore into a new database using:
call pg_dump -Fc -h server -d database -U user -p password -v -f dump.sql -t public.table1 -t public.table2
And I have no problems.
I then want to restore the dump by creating a new database with pg_restore using:
call pg_restore --clean --create -d temp -h server -p password -U user dump.sql
This gives me a "database temp does not exist" error. This should have created the database and restored it as far as I understand.
I However then create the "temp" database manually and run:
call pg_restore --clean --create -d temp -h server -p password -U user dump.sql
This follows through, but does not create the tables and gives me an error "relation table1" and "relation table2" does not exist and only creates the corresponding id_sequences for the two tables.
What I actually want is to not have to manually create the new database and that all tables in the backup is restored into a brand new database via pg_restore using:
call pg_restore --clean --create -d temp -h server -p password -U user dump.sql
as I understand it.
In order to create the database temp, pg_restore needs to be connected to a different database first.
So it won't do to use -d temp; you must specify an existing database, typically postgres.
pg_restore will connect to that database, issue CREATE DATABASE temp, connect to temp and proceed to restore the data.

How to restore postgres database into another database name

I use the postgres today
and got a problem
I dump the database that way
pg_dump zeus_development -U test > zeus_development.dump.out
what if I wnat to restore to another database zeus_production
How could I do?
Simple, first create your database using template0 as your template database:
createdb -U test -T template0 zeus_production
Then, restore your dump on this database:
psql -U test zeus_production -f /path/to/zeus_development.dump.out
When restoring, always use template0 explicit, as it is always an empty and unmodifiable database. If you don't use an explicit template, PostgreSQL will assume template1, and if it has some objects, like a table or function that your dumped database already has, you will get some errors while restoring.
Nonetheless, even if you were restoring on a database with the same name (zeus_development) you should create (or recreate) it the same way. Unless you used -C option while dumping (or -C of pg_restore if using a binary dump), which I don't recommend, because will give you less flexibility (like restoring on a different database name).
The PostgresSQL documentation has influenced me to use the custom format. I've been using it for years and it seems to have various advantages but your mileage may vary. That said, here is what worked for me:
pg_restore --no-owner --dbname postgres --create ~/Desktop/pg_dump
psql --dbname postgres -c 'ALTER DATABASE foodog_production RENAME TO foodog_development'
There was no foodog_development nor foodog_production databases existing before the sequence.
This restores the database from the dump (~/Desktop/pg_dump) which will create it with the name it was dumped as. The rename names the DB to whatever you want.
The --no-owner may not be needed if your user name is the same on both machines. In my case, the dump was done as user1 and the restore done as user2. The new objects need to be owned by user2 and --no-owner achieves this.
Isn't it easier to simply do the following?
createdb -U test -T zeus_development zeus_production
This has an answer on dba.stackexchange, which I reproduce here:
Let's define a few variables to make the rest easier to copy/paste
old_db=my_old_database
new_db=new_database_name
db_dump_file=backups/my_old_database.dump
user=postgres
The following assumes that your backup was created with the "custom" format like this:
pg_dump -U $user -F custom $old_db > "$db_dump_file"
To restore $db_dump_file to a new database name $new_db :
dropdb -U $user --if-exists $new_db
createdb -U $user -T template0 $new_db
pg_restore -U $user -d $new_db "$db_dump_file"
Here's a hacky way of doing it, that only works if you can afford the space and time to use regular .sql format, and if you can safely sed out your database name and user.
$ pg_dump -U my_production_user -h localhost my_production > my_prod_dump.sql
$ sed -i 's/my_production_user/my_staging_user/g' my_prod_dump.sql
$ sed -i 's/my_production/my_staging/g' my_prod_dump.sql
$ mv my_prod_dump.sql my_staging_dump.sql
$ sudo su postgres -c psql
psql> drop database my_staging;
psql> create database my_staging owner my_staging_user;
psql> \c my_staging;
psql> \i my_staging_dump.sql
If your dump does not include the name, the restore will use the DB defined in DESTINATION. Both SOURCE and DESTINATION are Connection URLs.
Dump without --create
pg_dump \
--clean --if-exists \
--file ${dump_path} \
--format=directory \
--jobs 5 \
--no-acl \
--no-owner \
${SOURCE}
Restore without --create
pg_restore \
--clean --if-exists \
--dbname=${DESTINATION} \
--format=directory \
--jobs=5 \
--no-acl \
--no-owner \
$dump_path