REVOKE(7)
π¦ NAME
REVOKE β bestie, this is the take-backs command. It removes access privileges. That's it, that's the whole vibe π
PostgreSQL 17.11 docs, manual page 7, and yes we're getting into it π«Ά
β¨ SYNOPSIS
Okay so here's the shape of it β every single flavor of REVOKE, verbatim, no cap:
REVOKE [ GRANT OPTION FOR ]
{ { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER | MAINTAIN }
[, ...] | ALL [ PRIVILEGES ] }
ON { [ TABLE ] table_name [, ...]
| ALL TABLES IN SCHEMA schema_name [, ...] }
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ { SELECT | INSERT | UPDATE | REFERENCES } ( column_name [, ...] )
[, ...] | ALL [ PRIVILEGES ] ( column_name [, ...] ) }
ON [ TABLE ] table_name [, ...]
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ { USAGE | SELECT | UPDATE }
[, ...] | ALL [ PRIVILEGES ] }
ON { SEQUENCE sequence_name [, ...]
| ALL SEQUENCES IN SCHEMA schema_name [, ...] }
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ { CREATE | CONNECT | TEMPORARY | TEMP } [, ...] | ALL [ PRIVILEGES ] }
ON DATABASE database_name [, ...]
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ USAGE | ALL [ PRIVILEGES ] }
ON DOMAIN domain_name [, ...]
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ USAGE | ALL [ PRIVILEGES ] }
ON FOREIGN DATA WRAPPER fdw_name [, ...]
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ USAGE | ALL [ PRIVILEGES ] }
ON FOREIGN SERVER server_name [, ...]
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ EXECUTE | ALL [ PRIVILEGES ] }
ON { { FUNCTION | PROCEDURE | ROUTINE } function_name [ ( [ [ argmode ] [ arg_name ] arg_type [, ...] ] ) ] [, ...]
| ALL { FUNCTIONS | PROCEDURES | ROUTINES } IN SCHEMA schema_name [, ...] }
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ USAGE | ALL [ PRIVILEGES ] }
ON LANGUAGE lang_name [, ...]
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ { SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] }
ON LARGE OBJECT loid [, ...]
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ { SET | ALTER SYSTEM } [, ...] | ALL [ PRIVILEGES ] }
ON PARAMETER configuration_parameter [, ...]
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ { CREATE | USAGE } [, ...] | ALL [ PRIVILEGES ] }
ON SCHEMA schema_name [, ...]
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ CREATE | ALL [ PRIVILEGES ] }
ON TABLESPACE tablespace_name [, ...]
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ USAGE | ALL [ PRIVILEGES ] }
ON TYPE type_name [, ...]
FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
REVOKE [ { ADMIN | INHERIT | SET } OPTION FOR ]
role_name [, ...] FROM role_specification [, ...]
[ GRANTED BY role_specification ]
[ CASCADE | RESTRICT ]
where role_specification can be:
[ GROUP ] role_name
| PUBLIC
| CURRENT_ROLE
| CURRENT_USER
| SESSION_USER
π DESCRIPTION
So REVOKE revokes privileges that were, like, previously granted β from one or more roles. And the keyword PUBLIC is not a person, bestie, it's the implicitly defined group of all roles π
Wanna know what each privilege type actually means? Go read the GRANT command's description, it's the whole lore drop π
Now here's the β¨iconicβ¨ part, the thing everybody gets wrong: any particular role has the sum of:
- privileges granted directly to it,
- privileges granted to any role it is presently a member of,
- and privileges granted to
PUBLIC.
So likeβ¦ revoking SELECT from PUBLIC does not necessarily mean all roles lost SELECT on that object π β anyone who has it granted directly, or via another role, still has it. Same energy the other way: revoking SELECT from a user might not stop that user from using SELECT at all if PUBLIC or another membership role still has SELECT rights. Sneaky, I know π
If you say GRANT OPTION FOR, then only the grant option for the privilege gets revoked β not the privilege itself. Otherwise? Both the privilege and the grant option are gone, bye π
Okay, dependent privileges, stay with me π§ If a user holds a privilege with grant option and has granted it to other users, then the privileges those other users hold are called dependent privileges. If the privilege or grant option held by the first user is being revoked and dependent privileges exist:
- if
CASCADEis specified β those dependent privileges also get revoked π₯ - if
CASCADEis not specified β the revoke action fails π
And this recursive revocation only affects privileges granted through a chain of users that is traceable to the user who is the subject of this REVOKE command. So the affected users might effectively keep the privilege if it was also granted through other users. Main character loophole, honestly π
When you revoke privileges on a table, the corresponding column privileges (if any) are automatically revoked on each column of the table too β¨. But flip it: if a role has been granted privileges on a table, then revoking the same privileges from individual columns will have no effect. Noted π«‘
When you're revoking membership in a role, GRANT OPTION is instead called ADMIN OPTION β but the behavior is similar, same vibe different name π
. Two things though:
Heads up, bestie: in releases prior to PostgreSQL 16, dependent privileges were not tracked for grants of role membership, and thusCASCADEhad no effect for role membership. That is no longer the case π Also: this form of the command does not allow the noise wordGROUPinrole_specification.
And just like ADMIN OPTION can be removed from an existing role grant, you can also revoke INHERIT OPTION or SET OPTION. That's equivalent to setting the value of the corresponding option to FALSE β
π NOTES
A user can only revoke privileges that were granted directly by that user. Example time, because this one's a whole saga π:
- User A grants a privilege with grant option to user B.
- User B then grants it to user C.
- User A cannot revoke the privilege directly from C. Nope. Not happening.
- Instead, user A could revoke the grant option from B and use
CASCADEso the privilege gets revoked from C in turn β¨
Another one: if both A and B have granted the same privilege to C, A can revoke their own grant but not B's β so C will still effectively have the privilege. The math is mathing π₯
When a non-owner of an object tries to REVOKE privileges on it:
- If the user has no privileges whatsoever on the object β the command fails outright π
- As long as some privilege is available β the command proceeds, but it will revoke only those privileges for which the user has grant options.
- The
REVOKE ALL PRIVILEGESforms will issue a warning message if no grant options are held. - The other forms will issue a warning if grant options for any of the privileges specifically named in the command aren't held.
- (In principle these statements apply to the object owner as well, but since the owner is always treated as holding all grant options, those cases can never occur. Owner privilege, literally π)
If a superuser chooses to issue a GRANT or REVOKE command, the command is performed as though it were issued by the owner of the affected object. (Since roles do not have owners, in the case of a GRANT of role membership, the command is performed as though it were issued by the bootstrap superuser.) And since all privileges ultimately come from the object owner β possibly indirectly via chains of grant options β it is possible for a superuser to revoke all privileges, but that might require use of CASCADE as stated above π
REVOKE can also be done by a role that is not the owner of the affected object, but is a member of the role that owns the object, or is a member of a role that holds privileges WITH GRANT OPTION on the object. In that case, the command is performed as though it were issued by the containing role that actually owns the object or holds the privileges WITH GRANT OPTION π«Ά
Example, because examples slay: if table t1 is owned by role g1, of which role u1 is a member, then u1 can revoke privileges on t1 that are recorded as being granted by g1. That includes grants made by u1 as well as by other members of role g1 β¨
β οΈ Okay this one's important: if the role executingREVOKEholds privileges indirectly via more than one role membership path, it is unspecified which containing role will be used to perform the command. Best practice? UseSET ROLEto become the specific role you want to do theREVOKEas. Otherwise you might revoke privileges other than the ones you intended, or not revoke anything at all ππ
See Section 5.8 for more info about specific privilege types, plus how to inspect objects' privileges π
πΈ EXAMPLES
Revoke insert privilege for the public on table films:
REVOKE INSERT ON films FROM PUBLIC;
Revoke all privileges from user manuel on view kinds:
REVOKE ALL PRIVILEGES ON kinds FROM manuel;
Note that this actually means βrevoke all privileges that I grantedβ π β it's not "all privileges ever", it's yours.
Revoke membership in role admins from user joe:
REVOKE admins FROM joe;
π¦ COMPATIBILITY
The compatibility notes of the GRANT command apply analogously to REVOKE. The keyword RESTRICT or CASCADE is required according to the standard, but PostgreSQL assumes RESTRICT by default π (defaults are so cozy)
π SEE ALSO
GRANT(7)ALTER DEFAULT PRIVILEGES(ALTER_DEFAULT_PRIVILEGES(7))
Okay that's the whole page, bestie β you ate that π β¨ This was PostgreSQL 17.11 documentation, dated 2026, manual page REVOKE(7). Go forth and revoke responsibly, mwah π«Άπ
π¦ where this page comes from
- opensuse-leap 16.0: postgresql17 17.11-160000.1.1 Β· PostgreSQL
- opensuse-leap 16.0: postgresql17 17.11-160000.1.1 Β· PostgreSQL
- opensuse-leap 16.0: postgresql17 17.11-160000.1.1 Β· PostgreSQL
- opensuse-leap 16.0: postgresql17 17.11-160000.1.1 Β· PostgreSQL
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms