如何编写一个SQL脚本,在PostgreSQL 9.1中创建一个角色,但如果它已经存在,又不会引发错误?

当前的脚本只是:

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;

... 但这不起作用——普通SQL似乎不支持IF.

我有一个批处理文件,可以创建PostgreSQL 9.1数据库、角色和其他一些东西.它称为psql.exe,传递要运行的SQL脚本的名称.到目前为止,所有这些脚本都是纯SQL,如果可能的话,我希望避免使用PL/pgSQL之类的脚本.

推荐答案

以类似于你所想的方式简化:

DO
$do$
BEGIN
   IF NOT EXISTS (
      SELECT FROM pg_catalog.pg_roles  -- SELECT list can be empty for this
      WHERE  rolname = 'my_user') THEN

      CREATE ROLE my_user LOGIN PASSWORD 'my_password';
   END IF;
END
$do$;

(以@a_horse_with_no_name的答案为基础,改进为@Gregory's comment.)

例如,与CREATE TABLE不同,CREATE ROLE没有IF NOT EXISTS条款(至少第12页).在纯SQL中执行动态DDL语句.

除非使用另一个PL,否则无法请求"避免PL/pgSQL".DO statement使用plpgsql作为默认过程语言.语法允许省略显式声明:

DO [ LANGUAGE lang_name ] code
...
lang_name
The name of the procedural language the code is written in. If omitted, the default is plpgsql.

Sql相关问答推荐

按postquist中的日期查询json列

帮助修复查询以识别SQL DW中数据中的递归关系

SQL使最终结果显示两个表后的所有数据(匹配和不匹配)?

Stack Exchange站点上的最短帖子(按正文长度计算,用户名为原始发帖(SEDE))

有没有办法在每次计算每一行的数据时更新2个值?

提高写密集型表的查询性能

LEFT JOIN不显示计数0我期望的方式

在SQL中使用类别值将行转置为列

PostgreSQL中的合并命令是原子的,还是需要一些类似于SQL Server版本的内容?

SQL:如何查找聚合满足条件的连续日期

如何为该查询编写正确分区依据

MS Access问题查询中的自定义字段

在Athena中使用regexp提取括号前的字符串值

Postgres SQL查询从字符串中获取邮箱地址

删除所有订单中可用的重复值

将SQL Server查询改进为;线程安全;

POSTGRES to_timestamp() 假定 UTC 字符串为本地时间

按所选的值将记录分组到不同的列中

PostgreSQL如何将Unix纪元时间戳转换为日期时间并进行拼接

批量更改WooCommerce中所有产品的税收状态