创buildPostgreSQL ROLE(用户),如果它不存在

如何编写一个SQL脚本来在PostgreSQL 9.1中创build一个ROLE,但是如果它已经存在则不会引发错误?

目前的脚本只有:

CREATE ROLE my_user LOGIN PASSWORD 'my_password'; 

如果用户已经存在,则失败。 我想要这样的东西:

 IF NOT EXISTS (SELECT * FROM pg_user WHERE username = 'my_user') BEGIN CREATE ROLE my_user LOGIN PASSWORD 'my_password'; END; 

…但这不起作用 – IF似乎不支持在普通的SQL。

我有一个batch file,创build一个PostgreSQL 9.1数据库,angular色和一些其他的东西。 它调用psql.exe,传入一个SQL脚本的名字来运行。 到目前为止,所有这些脚本都是普通的SQL,如果可能的话,我想避免使用PL / pgSQL等。

以@a_horse_with_no_name的答案为基础,我会以类似的方式简化你已经想到的东西:

 DO $body$ BEGIN IF NOT EXISTS ( SELECT -- SELECT list can stay empty for this FROM pg_catalog.pg_user WHERE usename = 'my_user') THEN CREATE ROLE my_user LOGIN PASSWORD 'my_password'; END IF; END $body$; 

与例如CREATE TABLE不同, CREATE ROLE (还)没有IF NOT EXISTS子句。 而且你不能在纯SQL中执行dynamic的DDL语句。

您的“避免PL / pgSQL”的请求是不可能的(除了使用另一个PL)。 DO语句也使用PL/pgSQL 。 语法允许省略显式声明:

DO [ LANGUAGE lang_name ] code

LANG_NAME
程序语言的代码被写入的名称。如果省略,则默认为plpgsql

或者,如果angular色不是任何数据库对象的所有者,可以使用:

 DROP ROLE IF EXISTS my_user; CREATE ROLE my_user LOGIN PASSWORD 'my_password'; 

但是只有当放弃这个用户不会造成任何伤害。

正如你在9.x上,你可以把它包装成一个DO语句:

 do $body$ declare num_users integer; begin SELECT count(*) into num_users FROM pg_user WHERE usename = 'my_user'; IF num_users = 0 THEN CREATE ROLE my_user LOGIN PASSWORD 'my_password'; END IF; end $body$ ; 

这是一个使用plpgsql的通用解决scheme:

 CREATE OR REPLACE FUNCTION create_role_if_not_exists(rolename NAME) RETURNS TEXT AS $$ BEGIN IF NOT EXISTS (SELECT * FROM pg_roles WHERE rolname = rolename) THEN EXECUTE format('CREATE ROLE %I', rolename); RETURN 'CREATE ROLE'; ELSE RETURN format('ROLE ''%I'' ALREADY EXISTS', rolename); END IF; END; $$ LANGUAGE plpgsql; 

用法:

 posgres=# SELECT create_role_if_not_exists('ri'); create_role_if_not_exists --------------------------- CREATE ROLE (1 row) posgres=# SELECT create_role_if_not_exists('ri'); create_role_if_not_exists --------------------------- ROLE 'ri' ALREADY EXISTS (1 row) 

我的团队在一台服务器上遇到了多个数据库的情况,具体取决于连接到哪个数据库, SELECT * FROM pg_catalog.pg_user没有返回相应的ROLE,正如@ erwin-brandstetter和@a_horse_with_no_name所提出的。 已执行的条件块,我们role "my_user" already exists

不幸的是我们不确定确切的条件,但是这个解决scheme解决了这个问题:

  DO $body$ BEGIN CREATE ROLE my_user LOGIN PASSWORD 'my_password'; EXCEPTION WHEN others THEN RAISE NOTICE 'my_user role exists, not re-creating'; END $body$ 

排除其他例外情况可能更具体。

您可以通过parsing以下输出来在batch file中执行此操作:

 SELECT * FROM pg_user WHERE usename = 'my_user' 

然后再次运行psql.exe ,如果该angular色不存在。