创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色不存在。