I'm in the middle of a database server migration and I can't figure (after googling and searching here) how can I list the database privileges (or all the privileges across the server) on PostgreSQL using the psql command line tool?

I'm on Ubuntu 11.04 and my PostgreSQL version is 8.2.x.

postgres=> \l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges   
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres

The docs on Privileges give an explanation of how to interpret the output. For specific privileges on a table of the current database, use \z myTable.

  • 19
    \z myTable is perfect for ensuring that you've successfully granted access to someone and avoiding looking like an idiot when you say "okay does it work now? it doesn't???" – ijoseph Jul 17 '18 at 17:50

perhaps you mean listing users and their privileges for a database - I can't quite tell from the question:

postgres=> \du
                             List of roles
    Role name    |  Attributes  |                    Member of
 dba             | Create role  | {util_user,helpdesk_user,helpdesk_admin}
 helpdesk_admin  | Cannot login | {helpdesk_user}
 helpdesk_user   | Cannot login | {helpdesk_reader}
 jack            |              | {helpdesk_admin}
 postgres        | Superuser    | {}
                 : Create role
                 : Create DB
  • Nope I wanted a way to list the privileges of a specific database, but I already figured it out. Owner of the database always has all privileges, right? And afterwards we can add more privileges on the database to other users/groups. Those are listed with the \l command. But very thanks anyway. – pedrosanta Aug 18 '11 at 16:20

You can do that by following:

SELECT grantee, privilege_type 
FROM information_schema.role_table_grants 
WHERE table_name='mytable'

This gives you this kind of output:

mail=# select grantee, privilege_type from information_schema.role_table_grants where table_name='aliases';
   grantee    |  privilege_type
 mailreader   |  INSERT
 mailreader   |  SELECT
 mailreader   |  UPDATE
 mailreader   |  DELETE
 mailreader   |  TRUNCATE
 mailreader   |  REFERENCES
 mailreader   |  TRIGGER
(7 rows)


Using psql meta-commands:


Going over the page with Ctrl+F gives:

\ddp [ pattern ] Lists default access privilege settings.

\dp [ pattern ] Lists tables, views and sequences with their associated access privileges.

\l[+] [ pattern ] List the databases in the server and show .... access privileges.

Also mentioned above, but not found with word "privileges" on the manual page:

\du+ for roles with login and \dg+ for roles without - will have a filed "Member of" where you find roles granted to roles.

I deliberately skip function and language privileges here, found in psql manual as barely manipulated (and if you do use those privileges you wont come here for an advise). same for user defined types, domains and so on - using "+" after the meta-command will show you privileges if applicable.

A little extreme way to check the privileges is dropping the user in transaction, e.g.:

s=# begin; drop user x;
Time: 0.124 ms
ERROR:  role "x" cannot be dropped because some objects depend on it
DETAIL:  privileges for type "SO dT"
privileges for sequence so
privileges for schema bin
privileges for table xx
privileges for table "csTest"
privileges for table tmp_x
privileges for table s1
privileges for table test
Time: 0.211 ms
s=# rollback;
Time: 0.150 ms

When the list is longer than N, (at least in 9.3), warning with list of privileges is collapsed, but you still can find it full in logs...

  • 1
    In v12 \du+and \dg+seems to return same results. I have 2 roles with NOLOGINoption and both are listed with both commands. Checked with \?and it gives same description for both commands so I guess the role-with-login vs user distinction is no longer available. – EAmez Mar 18 at 14:16

Undercovers psql uses the bellow query when you issue \du command.

SELECT r.rolname, r.rolsuper, r.rolinherit,
  r.rolcreaterole, r.rolcreatedb, r.rolcanlogin,
  r.rolconnlimit, r.rolvaliduntil,
  ARRAY(SELECT b.rolname
        FROM pg_catalog.pg_auth_members m
        JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid)
        WHERE m.member = r.oid) as memberof
, r.rolreplication
, r.rolbypassrls
FROM pg_catalog.pg_roles r
WHERE r.rolname !~ '^pg_'
  • ` "ERROR: column r.rolbypassrls does not exist\n\nLINE 9: , r.rolbypassrls\n\n ^\n",` unfortunately does not work – ribamar Dec 31 '18 at 15:16

A (possibly obvious) additional step is become the postgres user, otherwise you may get errors about roles not existing.

sudo su - postgres
psql -l


postgres=> \l

This is how you can list all privileges of a role (grantee):

SELECT grantor, grantee, table_schema, table_name, privilege_type
FROM information_schema.table_privileges
WHERE grantee = 'myuser'

Will result in:

 grantor  | grantee  | table_schema | table_name | privilege_type
 postgres | myuser   | myapp        | employees  | INSERT
 postgres | myuser   | myapp        | employees  | SELECT
 postgres | myuser   | myapp        | employees  | UPDATE
 postgres | myuser   | myapp        | employees  | DELETE

Works in PG 10


This is my query composed of multiple answers on this question:

SELECT grantee AS user, CONCAT(table_schema, '.', table_name) AS table, 
        WHEN COUNT(privilege_type) = 7 THEN 'ALL'
        ELSE ARRAY_TO_STRING(ARRAY_AGG(privilege_type), ', ')
    END AS grants
FROM information_schema.role_table_grants
GROUP BY table_name, table_schema, grantee;

This results in something like this:

| user |    table     |     grants     |
| foo  | schema.table | ALL            |
| bar  | schema.table | SELECT, INSERT |
  • 2
    Getting this error in pg 9.4 - ERROR: could not find array type for data type information_schema.character_data – Adam Mulla Nov 4 '20 at 7:40

You can input by following:

SELECT * FROM pg_roles;

and you will get

rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolconnlimit | rolpassword | rolvaliduntil | rolbypassrls | rolconfig | oid

maybe here you will think that there are too many roles, and this time, you can use WHERE to select what role you want to see

SELECT * FROM pg_roles WHERE rolname='your role name';

In fact, you can also just input


and you will see all roles you created instead of default

  • 1
    How is this different from existing answers posted earlier? – mustaccio Jun 21 '20 at 14:56
  • Here as a supplement to the previous, I think, the previous answers were missing this part or not concise enough. – Ricky Xu Jun 21 '20 at 15:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.