How to execute "DROP OWNED BY" only if the user exists? - postgresql

I'm trying to write a bash script that will create a Postgres database, as well as the user and the user privileges to access that database. I'm using Postgres 9.6. I have the below ...
create_db_command="SELECT 'CREATE DATABASE $DB_NAME' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '$DB_NAME')\gexec"
drop_owned_by_command="DROP OWNED BY $DB_USER;"
drop_role_command="DROP ROLE IF EXISTS $DB_USER;"
create_user_command="create user $DB_USER with encrypted password '$DB_PASS';"
grant_privs_command="grant all privileges on database $DB_NAME to $DB_USER;"
PGPASSWORD=$ROOT_PASSWORD
# This command creates the db if it doesn't already exist
echo "SELECT 'CREATE DATABASE $DB_NAME' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '$DB_NAME')\gexec" | psql -U$PG_USER
psql -U$PG_USER $DB_NAME -c "$drop_owned_by_command"
psql -U$PG_USER -c "$drop_role_command"
psql -U$PG_USER -c "$create_user_command"
psql -U$PG_USER -c "$grant_privs_command"
The problem is when the script is run the very first time, the command
DROP OWNED BY $DB_USER;
fails because the user does not yet exist. Is there a way to write the above command so that it will only run if the user exists? Similar to DROP USER IF EXISTS ..., but DROP OWNED has no IF EXISTS clause.

You can use a similar technique like you already have for CREATE DATABASE.
In the shell:
drop_owned_by_command="SELECT 'DROP OWNED BY $DB_USER' FROM pg_roles WHERE rolname = '$DB_USER'\gexec"
echo $drop_owned_by_command | psql -U$PG_USER $DB_NAME
The SELECT only returns a row (containing the DDL command) if the role a actually exists. This is in turn executed by the psql command \gexec.
So we have a combination of SQL and psql commands and cannot use psql -c since, quoting the manual on --command:
command must be either a command string that is completely parsable by the server (i.e., it contains no psql-specific features),
or a single backslash command. Thus you cannot mix SQL and psql
meta-commands within a -c option.
Instead, pipe the echo to psql like demonstrated - and like suggested in the manual and in my related answer below and like you already do for CREATE DATABASE.
Related:
Simulate CREATE DATABASE IF NOT EXISTS for PostgreSQL?
Shell script to execute pgsql commands in files

Related

How to create user in postresql version 12?

I have loged in postresql as default postgres user:
psql -U postres
and following the official documentation: https://www.postgresql.org/docs/12/app-createuser.html I have type this:
create user -d -e --role=myrole -r -s myuser;
and nothing happens. Postresql ignores the command.
\du
does not return myuser in user list.
It ignores the command when added any option, only this works:
create user myuser;
CREATE USER is a SQL statement that has its own syntax https://www.postgresql.org/docs/12/sql-createuser.html whereas createuser is an executable that has a different syntax: https://www.postgresql.org/docs/12/app-createuser.html: you cannot mix them.

postgresql: run SQL commands using psql in commandline

I have the below three lines to be run in commandline using psql how can i do it.
CREATE DATABASE myproject;
CREATE USER myprojectuser WITH PASSWORD 'password';
GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;
I just want to pass the sql strings as it is.
As per the docs psql -c 'command;'
psql -c 'CREATE DATABASE myproject;' -c "CREATE USER myprojectuser WITH PASSWORD 'password';" -c 'GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;'
As #horse suggested -f filename is a better option. You can also put them into a variable using a here document and execute it with the -c option .
read -r -d '' my_sqls << EOM
CREATE DATABASE myproject;
CREATE USER myprojectuser WITH PASSWORD 'password';
GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;
EOM
psql -c "$my_sqls" # running all the lines.

PostgreSQL command Automation in batch script

I need to automate the below commands through batch job, is there a way to do it. Currently command prompt is stopping after executing the first step(psql -U nrgadmin -d enwdb). Inside the enwdb database, I need to manually execute the steps from begin to commit. Any help would be appreciated.
psql -U nrgadmin -d enwdb;
begin;
alter schema asset_enw rename to asset_enw_backup;
alter schema asset_import rename to asset_enw;
alter table enw.geom rename to geom_backup;
alter table enw.geom_backup set schema asset_enw_backup;
alter table import.geom set schema enw;
commit;
Put your commands in a script file and use the -f option of psql while running it.
psql -U nrgadmin -d enwdb -f myscript.sql
Or, if you are in a Unix environment, you could put it all in a here document in a shell script and run the shell script.
#!/bin/sh
psql -U nrgadmin -d enwdb <<EOF
BEGIN;
alter schema asset_enw rename to asset_enw_backup;
#other statements
#--
COMMIT;
EOF

How backup and restore only list(name) databases, roles and right for databases in postgresql without data?

How backup and restore only list(name) databases, roles and right for databases in postgresql without data?
Bash script for get list database postgresql
sudo -i -u postgres psql -t -A -c 'SELECT datname FROM pg_database'
But how restore databases and relationship for roles and databases in postgresql?
Vao Tsun answer:
to prepare sql with database list for creation use smth like: psql -c
"select 'create database '||datname||';' from pg_database where not
datistemplate and datname != 'postgres';" -At >cdbs.sql, to create
database from a list, use psql -f cdbs.sql against new cluster
But all restored databases have owner postgres.
How restore databases with owner?
Thanks
from top of the head - try:
to get all roles, use pg_dumpall -g
to get permissions use pg_dump -s >to_file.sql and then psql -f to_file.sql ignoring creations errors.
to prepare sql with database list for creation use smth like: psql -c "select 'create database '||datname||';' from pg_database where not datistemplate and datname != 'postgres';" -At >cdbs.sql, to create database from a list, use psql -f cdbs.sql against new cluster

Load sql file data in to single table in postgres

I have sql file(single_table_data.sql) that contains data of only one table(I have taken dump of only one table from server)
Now i have to insert this sql file in to only single table in my database,
so how to import sql file in to single table in postgres ?
Edit
For example i had database name SpeedData and table name CurrentTable, so now i want to
insert entire sql file data in to this table CurrentTable
Note: The sql file contains only insert statements(not even create statements)
From the documentation:
psql dbname < infile
This should create a new table with the name of the previously dumped one and insert all data into it. Replace dbname with the name of the new database and infile with the name/path of the file containing the dump, in your case (single_table_data.sql)
If the dump contains only the insert statements, create the table by hand and then execute
psql -U your_username -d dbname -f single_table_data.sql
You can simply import sql dump data into your postgres db.
if you have already created DB then don't need to follow 1st step:-
STEP=1
open terminal then run following commands to create postgres database and user:-
sudo -u postgres psql
postgres=# create database mydb;
postgres=# create user myuser with encrypted password 'mypass';
postgres=# grant all privileges on database mydb to myuser;
STEP=2
\c used for selecting your database.
postgres=# \c yourdatabasename
\i used for importing dump data in database.
yourdatabasename=# \i path_of_your_dump_file for example:-
yourdatabasename=# \i /home/developer/projects/django_projects/db_dump.sql
If you face this type of error when you importing data:-
ERROR: role "yourusername" does not exist
so you can make superuser to your "db_user/yourusername" using this command:-
postgres=# ALTER USER fusion WITH SUPERUSER;
ALTER ROLE
If I understood correctly you want to create table from file and fill in with data.
Correct command is
PGPASSWORD=<password> psql -f /home/.../filename.sql -h localhost -d database_name -U user_name