使用匿名块中的变量创建用户密码

时间:2018-03-08 09:26:23

标签: sql postgresql plpgsql dynamic-sql

如果此类登录尚不存在,我想创建一个包含_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$$$之间有什么区别?

2 个答案:

答案 0 :(得分:1)

要参数化标识符或语法元素,通常需要将动态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都是硬编码的,但您可以简化,如下所示:

  

$DO$$$之间有什么区别?

请参阅:

答案 1 :(得分:0)

使用自定义选项的另一种方法(引用Erwin的较早答案):

又名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 vars插值和sql结合使用,通常可以更容易地获得相同的结果,如下所示: https://github.com/YordanGeorgiev/qto/blob/master/src/bash/qto/funcs/provision-db-admin.func.sh