I am trying to run following command:
sshpass -p "pass" ssh [email protected] "pg_dump -Fc -U foo some_db" | pg_restore --create --dbname=new_db
failed: FATAL: database "new_db" does not exist
This is because it is the way pg_restore works.
pg_restore manual reads as follow :
-C, --create Create the database before restoring into it. If --clean is also specified, drop and recreate the target database before connecting to it.
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.
The -d will restore in the given database if and only if -C is not used. If -C is used, the database is used as a "launchpad", not as the destination.
Let me reword @Izap's answer, because I had to read all answers over and over to figure things out...
The database management tools need in some cases a database to connect to, in order to perform maintenance operations.
pg_restore needs one for example when asked to create the database we will restore data to.
Let's stop and define some terms here:
So the problem I see with
pg_restore is that it uses the same semantics (same option parameter) for 2 completely different things.
--dbname is understood as the maintenance database when
--create is used. However when it's not used,
--dbname suddenly becomes the target database.
Let's define these in our shell for clarity:
So, you have:
# Clean the target database, then restore into it
pg_restore --clean --dbname $TARGET_DB db.dump
# Create the database (which name is extracted from the dump)
pg_restore --create --dbname $MAINTENANCE_DB db.dump
# Create explicitly the database first
# Restore into that freshly created database (ignoring the name in the dump)
pg_restore --dbname $TARGET_DB db.dump
This means that by just removing the
--create option, one could inadvertently make
pg_restore use the maintenance database as the target database.
I wish they had made the choice of using
--maintenance-db like in
createdb, always using
--dbname for the target.
To be a bit more explicit, this is what I did that solved the problem for me:
Create an empty database with the name you want: (in my case the username was 'postgres')
psql -U [username]
It will then prompt you for your password. At this point you will be logged in as [username]. Type the following:
CREATE DATABASE [dbname];
Now exit the session and go back to your regular terminal session.
Restore the database from the file you have setting the target database name as that database name you just created.
cat [your_file_path/filename] | psql -U [username] [dbname]
Where [your_file_path/filename] is the location of the db file or text file you want to restore.