Olson CloudWorks 🚀

Create PostgreSQL ROLE user if it doesnt exist

September 19, 2026

📂 Categories: Sql
Create PostgreSQL ROLE user if it doesnt exist

Managing user access is crucial for any database system, and PostgreSQL is no exception. The ability to create PostgreSQL ROLE (user) if it doesn’t exist is a fundamental task for database administrators. It ensures that only authorized personnel can access sensitive data and perform specific operations. This blog post will guide you through the process of efficiently managing PostgreSQL roles, providing practical examples and best practices. We will explore how to automate role creation, enhance security, and maintain a well-organized database environment. Properly managing roles in PostgreSQL leads to improved security, easier administration, and better overall database performance. Let’s dive into the details of how to create roles only when they’re needed.

Understanding PostgreSQL Roles and Users

In PostgreSQL, roles and users are essentially the same thing. The term “role” encompasses both users and groups, providing a flexible way to manage database access and permissions. A role can be a user, which is a single entity that can log in and perform actions, or a group, which is a collection of users that share the same privileges. Using roles allows you to implement the principle of least privilege, granting users only the necessary permissions to perform their tasks. This reduces the risk of unauthorized access and data breaches. Properly understanding the distinction between roles and users, and how they relate to permissions, is the first step in effective PostgreSQL administration.

When you create PostgreSQL ROLE (user) if it doesn’t exist, you’re essentially creating a new identity within the database system. This identity can then be granted specific permissions, such as the ability to read, write, or execute data. It’s vital to carefully plan your role hierarchy and permission structure to ensure that users have the appropriate level of access. Overly permissive roles can create security vulnerabilities, while overly restrictive roles can hinder productivity. Therefore, a balanced approach is essential. By leveraging roles and groups effectively, you can simplify user management and enhance the overall security posture of your PostgreSQL database.

One of the key advantages of using roles is the ability to easily manage permissions across multiple users. For example, you can create a “read-only” role and grant it to all users who need to view data but not modify it. This makes it much easier to maintain consistent permissions and avoid the need to individually grant permissions to each user. According to a study by Gartner, “Organizations that implement robust access control mechanisms experience a 70% reduction in security incidents related to unauthorized access.” Gartner highlights the importance of well-defined roles in a comprehensive security strategy.

Checking for Existing Roles Before Creation

Before attempting to create PostgreSQL ROLE (user) if it doesn’t exist, it’s essential to check whether the role already exists. This prevents errors and ensures that your scripts are idempotent, meaning they can be run multiple times without unintended consequences. The most common way to check for an existing role is to use a SQL query that queries the pg_roles system catalog. This catalog contains information about all roles defined in the PostgreSQL database. By querying this catalog, you can determine whether a role with a specific name already exists.

Here’s a SQL query that can be used to check for an existing role:

SELECT 1 FROM pg_roles WHERE rolname = 'your_role_name';

This query will return a value of 1 if a role with the name ‘your_role_name’ exists, and will return no rows if the role does not exist. You can use this query within your scripts to conditionally create the role only if it doesn’t already exist. This approach ensures that you avoid errors and maintain the integrity of your database.

Featured Snippet: To avoid errors when creating roles, always check if the role exists first. Use the SQL query SELECT 1 FROM pg_roles WHERE rolname = ‘your_role_name’;. If the query returns a row, the role exists; otherwise, it doesn’t. This prevents conflicts and ensures idempotent scripts.

Using PL/pgSQL for Conditional Role Creation

PL/pgSQL is PostgreSQL’s procedural language, which allows you to write stored procedures and functions. You can use PL/pgSQL to create a function that checks for the existence of a role and creates it only if it doesn’t already exist. This provides a convenient and reusable way to manage role creation. Here’s an example of a PL/pgSQL function that creates a role if it doesn’t exist:

CREATE OR REPLACE FUNCTION create_role_if_not_exists(role_name TEXT, role_password TEXT) RETURNS VOID AS $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = role_name) THEN EXECUTE 'CREATE ROLE ' || quote_ident(role_name) || ' WITH LOGIN PASSWORD ' || quote_literal(role_password); END IF; END; $$ LANGUAGE plpgsql SECURITY DEFINER;

This function takes the role name and password as input and creates the role only if it doesn’t already exist. The quote_ident function is used to properly quote the role name, preventing SQL injection vulnerabilities. The quote_literal function is used to properly quote the password. Using PL/pgSQL functions can greatly simplify your database administration tasks. You can then call this function to create PostgreSQL ROLE (user) if it doesn’t exist.

Automating Role Creation with Scripts

Automating the process to create PostgreSQL ROLE (user) if it doesn’t exist is crucial for efficient database management. Manual role creation is time-consuming and error-prone, especially in large environments with many users. Automation helps to streamline the process, reduce the risk of human error, and ensure consistency across your database infrastructure. There are several ways to automate role creation, including using shell scripts, configuration management tools, and custom applications.

  • Shell Scripts: You can write shell scripts that use the psql command-line tool to connect to the PostgreSQL database and execute SQL commands. These scripts can be used to check for the existence of a role and create it if it doesn’t already exist.
  • Configuration Management Tools: Tools like Ansible, Chef, and Puppet can be used to automate the deployment and configuration of PostgreSQL databases, including the creation of roles. These tools allow you to define the desired state of your database infrastructure and automatically enforce that state.

Here’s an example of a shell script that uses psql to create a role if it doesn’t exist:

!/bin/bash ROLE_NAME="new_user" ROLE_PASSWORD="secure_password" DB_NAME="your_database" DB_USER="postgres" if psql -U "$DB_USER" -d "$DB_NAME" -t -c "SELECT 1 FROM pg_roles WHERE rolname='$ROLE_NAME'" | grep -q 1; then echo "Role '$ROLE_NAME' already exists." else psql -U "$DB_USER" -d "$DB_NAME" -c "CREATE ROLE \"$ROLE_NAME\" WITH LOGIN PASSWORD '$ROLE_PASSWORD';" echo "Role '$ROLE_NAME' created successfully." fi

This script connects to the PostgreSQL database, checks for the existence of the role, and creates it if it doesn’t already exist. Remember to adjust the variables to match your specific environment. Automating role creation can save you a significant amount of time and effort, and it also helps to ensure that your database infrastructure is configured consistently. You can use this script to create PostgreSQL ROLE (user) if it doesn’t exist.

Best Practices for Role Management

Effective role management is essential for maintaining the security and integrity of your PostgreSQL database. Here are some best practices to follow when managing roles:

  1. Principle of Least Privilege: Grant users only the necessary permissions to perform their tasks. Avoid granting overly permissive roles that could create security vulnerabilities.
  2. Role-Based Access Control (RBAC): Use roles to group users with similar responsibilities and grant permissions to the roles rather than individual users. This simplifies user management and ensures consistency.
  3. Regular Auditing: Regularly review user permissions and roles to ensure that they are still appropriate. Remove any unnecessary permissions or roles.

Implementing strong password policies is also crucial. Enforce complex passwords and require users to change their passwords regularly. You can use the ALTER ROLE command to set password policies for individual roles. “Strong password policies are the first line of defense against unauthorized access,” according to the National Institute of Standards and Technology (NIST). NIST provides comprehensive guidelines on password management.

Another important best practice is to use secure connections when connecting to the database. Use SSL/TLS encryption to protect sensitive data in transit. Configure your PostgreSQL server to require SSL connections and ensure that your clients are properly configured to use SSL. By following these best practices, you can significantly enhance the security and manageability of your PostgreSQL database. These are important to help you create PostgreSQL ROLE (user) if it doesn’t exist safely.

Infographic here
FAQ: Creating PostgreSQL Roles ------------------------------
How do I list all existing roles in PostgreSQL?
You can list all existing roles by querying the pg\_roles system catalog: SELECT rolname FROM pg\_roles;
How do I grant a role specific privileges?
Use the GRANT command to grant specific privileges to a role. For example: GRANT SELECT, INSERT ON my\_table TO my\_role;
How do I revoke privileges from a role?
Use the REVOKE command to revoke privileges from a role. For example: REVOKE SELECT ON my\_table FROM my\_role;
Can a role be a member of another role?
Yes, roles can be members of other roles. This allows you to create a hierarchy of roles and manage permissions more efficiently. Use the GRANT role\_name TO other\_role; command.
By understanding the principles and techniques outlined in this article, you can effectively manage user access in your PostgreSQL database. Remember to prioritize security, automate repetitive tasks, and follow best practices to ensure a well-organized and secure database environment. You can use this information to **create PostgreSQL ROLE (user) if it doesn't exist** in a safe and efficient manner.

We’ve covered a lot of ground, from understanding the basics of PostgreSQL roles to automating their creation and managing them effectively. Armed with this knowledge, you’re well-equipped to secure your databases and streamline administrative tasks. Don’t wait – start implementing these strategies today to enhance your PostgreSQL environment. Explore related topics like database security best practices, user permission management, and advanced PostgreSQL administration. For additional learning, check out the official PostgreSQL documentation here and read more about database role management on our blog.

Question & Answer :
How do I write an SQL script to create a ROLE in PostgreSQL 9.1, but without raising an error if it already exists?

The current script simply has:

CREATE ROLE my_user LOGIN PASSWORD 'my_password'; 

This fails if the user already exists. I’d like something like:

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

… but that doesn’t work - IF doesn’t seem to be supported in plain SQL.

I have a batch file that creates a PostgreSQL 9.1 database, role and a few other things. It calls psql.exe, passing in the name of an SQL script to run. So far all these scripts are plain SQL and I’d like to avoid PL/pgSQL and such, if possible.

Simple script (question asked)

Building on @a_horse_with_no_name’s answer and improved with @Gregory’s comment:

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$; 

Unlike, for instance, with CREATE TABLE there is no IF NOT EXISTS clause for CREATE ROLE (up to at least Postgres 14). And you cannot execute dynamic DDL statements in plain SQL.

Your request to “avoid PL/pgSQL” is impossible except by using another PL. The DO statement uses PL/pgSQL as default procedural language:

DO [ LANGUAGE lang_name ] code

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

No race condition

The above simple solution allows for a race condition in the tiny time frame between looking up the role and creating it. If a concurrent transaction creates the role in between we get an exception after all. In most workloads, that will never happen as creating roles is a rare operation carried out by an admin. But there are highly contentious workloads like @blubb mentioned.
@Pali added a solution trapping the exception. But a code block with an EXCEPTION clause is expensive. The manual:

A block containing an EXCEPTION clause is significantly more expensive to enter and exit than a block without one. Therefore, don’t use EXCEPTION without need.

Actually raising an exception (and then trapping it) is comparatively expensive on top of it. All of this only matters for workloads that execute it a lot - which happens to be the primary target audience. To optimize:

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$; 

Much cheaper:

  • If the role already exists, we never enter the expensive code block.
  • If we enter the expensive code block, the role only ever exists if the unlikely race condition hits. So we hardly ever actually raise an exception (and catch it).