在 PostgreSQL 9.1 中,如果角色已存在,则使用 CREATE ROLE 创建角色会失败。在编写数据库创建和角色管理脚本时,此限制带来了挑战。理想的解决方案是仅在角色不存在时有条件地执行 CREATE ROLE 语句。
一种方法是利用 PL/pgSQL 的 DO 块和 IF EXISTS 条件:
DO $do$ BEGIN IF EXISTS ( SELECT FROM pg_catalog.pg_roles WHERE rolname = 'my_user') THEN RAISE NOTICE 'Role "my_user" already exists. Skipping.'; ELSE CREATE ROLE my_user LOGIN PASSWORD 'my_password'; END IF; END $do$;
此脚本使用 SELECT 动态检查角色是否存在并执行 CREATE ROLE仅当角色不存在时。
此解决方案不会引入竞争条件。 IF EXISTS 条件确保仅当检查时角色不存在时才创建该角色。在检查和创建之间创建角色的任何并发事务都不会导致问题,因为该角色在 CREATE ROLE 执行时已经存在。
为了进一步优化脚本,可以使用嵌套块来避免异常处理程序的成本:
DO $do$ BEGIN IF EXISTS ( SELECT FROM pg_catalog.pg_roles WHERE rolname = 'my_user') THEN RAISE NOTICE 'Role "my_user" already exists. Skipping.'; ELSE BEGIN -- nested block CREATE ROLE my_user LOGIN PASSWORD 'my_password'; EXCEPTION WHEN duplicate_object THEN RAISE NOTICE 'Role "my_user" was just created by a concurrent transaction. Skipping.'; END; END IF; END $do$;
此脚本有效地执行检查并以最小的开销处理任何潜在的竞争条件。嵌套块确保仅当角色不存在或并发事务刚刚创建角色时才会创建角色,在这种情况下会发出通知。
以上是如何有条件地创建 PostgreSQL 角色以避免错误?的详细内容。更多信息请关注PHP中文网其他相关文章!