从匿名块中的变量创建带有密码的用户

spi*_*ula 4 sql postgresql dynamic-sql plpgsql

我想创建一个包含变量的脚本,_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$
Run Code Online (Sandbox Code Playgroud)

如何强制用变量的内容替换变量?

$DO$还有和之间有什么区别$$

Erw*_*ter 5

要参数化标识符或语法元素,通常需要将动态 SQL 与EXECUTE- 最好结合format()使用以方便使用。

\n

但实用程序命令(包括所有 SQL DDL 语句)根本不允许传递值或参数替换。您需要在执行之前连接完整的语句。看:

\n\n

你的代码将像这样工作:

\n
DO\n$do$\nDECLARE\n  _user text := \'myuser\';\n  _pass text := \'user!pass\';\nBEGIN\n   IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = _user) THEN\n      EXECUTE format(\n        \'CREATE USER %I WITH\n            LOGIN\n            NOSUPERUSER\n            CREATEDB\n            CREATEROLE\n            NOREPLICATION\n            PASSWORD %L\'\n         , _user\n         , _pass\n         );\n      RAISE NOTICE \'Created user "%"\', _user;\n   ELSE\n      RAISE NOTICE \'User "%" already exists, not creating it\', _user;\n   END IF;\nEND\n$do$\n
Run Code Online (Sandbox Code Playgroud)\n

但是,虽然_user_pass无论如何都是硬编码的,但您可以像这里演示的那样进行简化:

\n\n
\n

$DO$还有和之间有什么区别$$

\n
\n

看:

\n\n