如何只在用户存在的情况下才执行"DROP OWNED BY"?

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

我正在尝试编写一个 bash 脚本来创建一个 Postgres 数据库,以及用户和访问该数据库的用户权限。我正在使用 Postgres 9.6。我有以下...

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"

问题是当脚本第一次 运行 时,命令

DROP OWNED BY $DB_USER;

失败,因为用户尚不存在。有没有一种方法可以编写上述命令,使其仅在用户存在时才 运行 ?类似于 DROP USER IF EXISTS ...,但 DROP OWNED 没有 IF EXISTS 子句。

您可以使用与 CREATE DATABASE.
中已有的类似技术 在 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

如果角色a实际存在,SELECT只有returns一行(包含DDL命令)。这又由 psql 命令 \gexec.

执行

所以我们有 SQL 和 psql 命令的组合,不能使用 psql -c 因为 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.

相反,像演示的那样将回显通过管道传输到 psql - 就像手册和下面我的相关答案中所建议的那样,就像你已经为 CREATE DATABASE.

所做的那样

相关:

  • Simulate CREATE DATABASE IF NOT EXISTS for PostgreSQL?
  • Shell script to execute pgsql commands in files