从匿名块中的变量创建带密码的用户
Creating user with password from variables in anonymous block
我想创建一个脚本,其中包含变量 _user
和 _pass
以在 Postgres 数据库中创建用户 仅 如果这样的登录确实存在还不存在。我原以为这会起作用,但我不知道是什么问题:
DO
$DO$
DECLARE
_user TEXT := 'myuser';
_pass TEXT := 'user!pass';
BEGIN
IF NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = _user) THEN
RAISE NOTICE 'Creating user % ...',_user;
CREATE USER _user WITH
LOGIN
NOSUPERUSER
CREATEDB
CREATEROLE
NOREPLICATION
PASSWORD _pass;
RAISE NOTICE 'Created user %',_user;
ELSE
RAISE NOTICE 'User % already exists, not creating it',_user;
END IF;
END
$DO$
如何强制用变量的内容替换变量?
还有$DO$
和$$
有什么区别?
要参数化标识符或语法元素,您通常需要将动态 SQL 与 EXECUTE
结合使用 - 最好结合 format()
以便于使用。
但是实用程序命令(包括所有 SQL DDL 语句)根本不允许传递值或参数替换。您需要在执行之前连接完整的语句。参见:
您的代码将像这样工作:
DO
$do$
DECLARE
_user text := 'myuser';
_pass text := 'user!pass';
BEGIN
IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = _user) THEN
EXECUTE format(
'CREATE USER %I WITH
LOGIN
NOSUPERUSER
CREATEDB
CREATEROLE
NOREPLICATION
PASSWORD %L'
, _user
, _pass
);
RAISE NOTICE 'Created user "%"', _user;
ELSE
RAISE NOTICE 'User "%" already exists, not creating it', _user;
END IF;
END
$do$
但是,尽管 _user
和 _pass
无论如何都是硬编码的,您可以像此处演示的那样进行简化:
- Create PostgreSQL ROLE (user) if it doesn't exist
Also what is the difference between $DO$
and $$
?
参见:
- What are '$$' used for in PL/pgSQL
ab(使用)自定义选项的另一种方式(引用 Erwin 的旧答案):
- 来源:
- 来源:https://dba.stackexchange.com/a/213921/1245
这也可以启用从 bash 脚本传递变量:
又名 bash:
set -x
PGPASSWORD="${postgres_db_useradmin_pw:-}" psql -q -t -X \
-w -U "${postgres_db_useradmin:-}" \
-h $postgres_db_host -p $postgres_db_port \
-v ON_ERROR_STOP=1 \
-v postgres_db_user="${postgres_db_user:-}" \
-v postgres_db_user_pw="${postgres_db_user_pw:-}" \
-v postgres_db_name="${postgres_db_name:-}" \
-f "$sql_script" "${postgres_db_name:-}" > "$tmp_log_file" 2>&1
并在 pgsql
SET myvars.postgres_db_user TO :'postgres_db_user';
SET myvars.postgres_db_user_pw TO :'postgres_db_user_pw';
DO
$do$
BEGIN
EXECUTE format(
'CREATE ROLE %I WITH PASSWORD %L LOGIN'
, current_setting('myvars.postgres_db_user', true)::text
, current_setting('myvars.postgres_db_user_pw', true)::text
);
RAISE NOTICE 'Created user "%"',
current_setting('myvars.postgres_db_user', true)::text;
EXCEPTION WHEN OTHERS THEN
RAISE NOTICE 'User "%" already exists, not creating it',
current_setting('myvars.postgres_db_user', true)::text;
EXECUTE format(
'ALTER ROLE %I WITH PASSWORD %L LOGIN'
, current_setting('myvars.postgres_db_user', true)::text
, current_setting('myvars.postgres_db_user_pw', true)::text
);
END
$do$;
值得注意的是,通常通过组合 bash 变量插值和 sql 可以更容易地实现相同的结果,如下所示:
https://github.com/YordanGeorgiev/qto/blob/master/src/bash/qto/funcs/provision-db-admin.func.sh
我想创建一个脚本,其中包含变量 _user
和 _pass
以在 Postgres 数据库中创建用户 仅 如果这样的登录确实存在还不存在。我原以为这会起作用,但我不知道是什么问题:
DO
$DO$
DECLARE
_user TEXT := 'myuser';
_pass TEXT := 'user!pass';
BEGIN
IF NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = _user) THEN
RAISE NOTICE 'Creating user % ...',_user;
CREATE USER _user WITH
LOGIN
NOSUPERUSER
CREATEDB
CREATEROLE
NOREPLICATION
PASSWORD _pass;
RAISE NOTICE 'Created user %',_user;
ELSE
RAISE NOTICE 'User % already exists, not creating it',_user;
END IF;
END
$DO$
如何强制用变量的内容替换变量?
还有$DO$
和$$
有什么区别?
要参数化标识符或语法元素,您通常需要将动态 SQL 与 EXECUTE
结合使用 - 最好结合 format()
以便于使用。
但是实用程序命令(包括所有 SQL DDL 语句)根本不允许传递值或参数替换。您需要在执行之前连接完整的语句。参见:
您的代码将像这样工作:
DO
$do$
DECLARE
_user text := 'myuser';
_pass text := 'user!pass';
BEGIN
IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = _user) THEN
EXECUTE format(
'CREATE USER %I WITH
LOGIN
NOSUPERUSER
CREATEDB
CREATEROLE
NOREPLICATION
PASSWORD %L'
, _user
, _pass
);
RAISE NOTICE 'Created user "%"', _user;
ELSE
RAISE NOTICE 'User "%" already exists, not creating it', _user;
END IF;
END
$do$
但是,尽管 _user
和 _pass
无论如何都是硬编码的,您可以像此处演示的那样进行简化:
- Create PostgreSQL ROLE (user) if it doesn't exist
Also what is the difference between
$DO$
and$$
?
参见:
- What are '$$' used for in PL/pgSQL
ab(使用)自定义选项的另一种方式(引用 Erwin 的旧答案):
- 来源:
- 来源:https://dba.stackexchange.com/a/213921/1245 这也可以启用从 bash 脚本传递变量:
又名 bash:
set -x
PGPASSWORD="${postgres_db_useradmin_pw:-}" psql -q -t -X \
-w -U "${postgres_db_useradmin:-}" \
-h $postgres_db_host -p $postgres_db_port \
-v ON_ERROR_STOP=1 \
-v postgres_db_user="${postgres_db_user:-}" \
-v postgres_db_user_pw="${postgres_db_user_pw:-}" \
-v postgres_db_name="${postgres_db_name:-}" \
-f "$sql_script" "${postgres_db_name:-}" > "$tmp_log_file" 2>&1
并在 pgsql
SET myvars.postgres_db_user TO :'postgres_db_user';
SET myvars.postgres_db_user_pw TO :'postgres_db_user_pw';
DO
$do$
BEGIN
EXECUTE format(
'CREATE ROLE %I WITH PASSWORD %L LOGIN'
, current_setting('myvars.postgres_db_user', true)::text
, current_setting('myvars.postgres_db_user_pw', true)::text
);
RAISE NOTICE 'Created user "%"',
current_setting('myvars.postgres_db_user', true)::text;
EXCEPTION WHEN OTHERS THEN
RAISE NOTICE 'User "%" already exists, not creating it',
current_setting('myvars.postgres_db_user', true)::text;
EXECUTE format(
'ALTER ROLE %I WITH PASSWORD %L LOGIN'
, current_setting('myvars.postgres_db_user', true)::text
, current_setting('myvars.postgres_db_user_pw', true)::text
);
END
$do$;
值得注意的是,通常通过组合 bash 变量插值和 sql 可以更容易地实现相同的结果,如下所示: https://github.com/YordanGeorgiev/qto/blob/master/src/bash/qto/funcs/provision-db-admin.func.sh