DBMS 📂 SQL · 6 of 6 24 min read

DCL in SQL: GRANT and REVOKE — A Practice-Driven DBMS Tutorial

A hands-on DBMS tutorial on Data Control Language, covering everything needed to manage database permissions with GRANT and REVOKE. It explains object vs system privileges, GRANT syntax (including column-level and multi-user grants), WITH GRANT OPTION delegation, roles, the PUBLIC grantee, REVOKE, and the crucial difference between CASCADE and RESTRICT when revoking privileges that others depend on

Section 01

The Story That Explains DCL

Keys to the Rooms of a Building
Think of a database as a building full of locked rooms (the tables). The owner holds the master key and decides who may enter which room and what they may do inside — just look around, rearrange the furniture, or remove things entirely.

Handing someone a key is GRANT. Taking the key back is REVOKE. You can even give a trusted person a key and permission to cut copies for others (WITH GRANT OPTION). These two commands — GRANT and REVOKE — are the whole of DCL, the Data Control Language that governs who can do what in a database.

DCL (Data Control Language) manages privileges: the permissions that let a user perform actions on database objects. It has just two statements, GRANT and REVOKE, but they carry real weight — they are the front line of database security. This tutorial covers privileges, GRANT, roles, PUBLIC, WITH GRANT OPTION, REVOKE, and the all-important CASCADE behaviour, each with examples and animated diagrams.

🧮
The One Idea to Hold Onto

A privilege always has three parts: what action (SELECT, INSERT…), on which object (a table, view, or routine), and to whom (a user or role). Every GRANT and REVOKE statement simply fills in those three blanks.


Section 02

Where DCL Sits Among SQL Commands

SQL statements fall into four families. DCL is one of them — the one concerned purely with permissions.

🏗️
DDL
structure
CREATE, ALTER, DROP, TRUNCATE — defines and changes the schema itself.
✏️
DML
data
SELECT, INSERT, UPDATE, DELETE — reads and changes the rows inside tables.
🔑
DCL
permissions
GRANT, REVOKE — controls who is allowed to run the commands above.
💰
TCL
transactions
COMMIT, ROLLBACK, SAVEPOINT — controls the boundaries of a transaction.

Section 03

Two Kinds of Privileges

📂
Object privileges
on a specific object
Apply to a named table, view, or routine: SELECT, INSERT, UPDATE, DELETE, REFERENCES, EXECUTE.
🏢
System privileges
database-wide
Apply to the whole database: CREATE TABLE, CREATE USER, CREATE SESSION, DROP ANY TABLE, and similar administrative rights.
🃏
ALL PRIVILEGES
shorthand
A convenience that grants every object privilege the grantor can give on that object — use sparingly, since it is the opposite of least privilege.
Object privilegeLets the user…
SELECTread rows from the table or view
INSERTadd new rows (can be limited to specific columns)
UPDATEmodify existing rows (can be column-specific)
DELETEremove rows
REFERENCEScreate a foreign key that points at the table
EXECUTErun a stored procedure or function

Section 04

GRANT — Handing Out a Privilege

The GRANT statement gives one or more privileges on an object to one or more users or roles.

-- Syntax
GRANT privilege_list
ON    object
TO    grantee_list
[WITH GRANT OPTION];

-- Let an analyst read the employees table
GRANT SELECT
ON    employees
TO    analyst_amy;

-- Multiple privileges, multiple users, in one statement
GRANT SELECT, INSERT, UPDATE
ON    employees
TO    manager_mia, hr_clerk;

-- Column-level: allow updating only the salary column
GRANT UPDATE (salary)
ON    employees
TO    payroll_pat;
🔑 How GRANT Hands a Privilege to a User
GRANT SELECT ON employees TO analyst_amy hr_admin owner / grantor analyst_amy grantee SELECT ✓ can now read employees

The privilege token travels from the owner to the grantee; once it arrives, the grantee's box turns green and the access is live.


Section 05

WITH GRANT OPTION — Delegating the Power to Grant

Adding WITH GRANT OPTION lets the grantee pass the same privilege on to others. It is powerful and risky: you are no longer the only gatekeeper.

🔗 A Privilege Propagating Down a Delegation Chain
hr_admin owner analyst_amy WITH GRANT OPTION intern_raj grantee SELECT SELECT amy received SELECT and may re-grant it; she passes it to raj

With the grant option, analyst_amy becomes a grantor herself and extends the privilege to intern_raj.

-- Owner grants to amy AND lets her re-grant
GRANT SELECT ON employees TO analyst_amy WITH GRANT OPTION;

-- Now amy can legally do this herself
GRANT SELECT ON employees TO intern_raj;
⚠️
Delegation Creates Dependency Chains

Once amy grants to raj, raj's access depends on amy's. This dependency is exactly what makes revoking later complicated — pulling amy's privilege can pull raj's too. That is the CASCADE story in Section 09.


Section 06

Roles — Bundling Privileges

Granting the same five privileges to fifty users individually is a maintenance nightmare. A role is a named bundle of privileges; grant privileges to the role once, then grant the role to users. Change the role and everyone updates at once.

-- 1. Create a role and load it with privileges
CREATE ROLE hr_staff;
GRANT SELECT, INSERT, UPDATE ON employees TO hr_staff;

-- 2. Hand the whole bundle to users
GRANT hr_staff TO manager_mia, hr_clerk;

-- 3. Later, add one privilege to the role — every member gains it instantly
GRANT DELETE ON employees TO hr_staff;
🎯 Why Roles Win
Less work
Grant or revoke once on the role instead of once per user.
Consistency
Every member has exactly the same rights — no accidental drift.
Clarity
A role name like hr_staff documents intent far better than a scattered list of grants.

Section 07

PUBLIC — Granting to Everyone

The special grantee PUBLIC represents every current and future user. A privilege granted to PUBLIC is held by all.

-- Make a lookup table readable by absolutely everyone
GRANT SELECT ON country_codes TO PUBLIC;
🚨
Use PUBLIC With Great Care

PUBLIC is the broadest possible grant and quietly applies to users created after the grant too. Reserve it for genuinely public, non-sensitive reference data, and never for anything containing personal or confidential information.


Section 08

REVOKE — Taking a Privilege Back

The mirror image of GRANT. The structure is the same, with FROM in place of TO.

-- Syntax
REVOKE privilege_list
ON     object
FROM   grantee_list
[CASCADE | RESTRICT];

-- Remove the analyst's read access
REVOKE SELECT ON employees FROM analyst_amy;

-- Remove one privilege from a role (every member loses it)
REVOKE INSERT ON employees FROM hr_staff;

-- Take back only the ability to re-grant, keeping the privilege itself
REVOKE GRANT OPTION FOR SELECT ON employees FROM analyst_amy;
✔ GRANT
Property
Keyword TO
Gives a privilege
Optional WITH GRANT OPTION
Opens access
✖ REVOKE
Property
Keyword FROM
Removes a privilege
Optional CASCADE / RESTRICT
Closes access

Section 09

CASCADE vs RESTRICT — The Cascading Revoke

Recall the delegation chain: owner → amy (with grant option) → raj. When you revoke amy's privilege, what happens to raj — who only has access because amy granted it? That is decided by CASCADE or RESTRICT.

🔄 REVOKE … CASCADE — the revoke flows down the chain
hr_admin owner (keeps it) analyst_amy revoked directly intern_raj revoked by cascade 1. Chain established — both can read ✓ amy: SELECT    ✓ raj: SELECT 2. REVOKE SELECT ON employees FROM amy CASCADE ✗ amy loses it — and so does raj CASCADE removes every privilege that depended on the one being revoked

Because raj's access was derived from amy's, CASCADE revokes raj's privilege automatically. The owner is unaffected.

CASCADE
Behaviour
Revokes the privilege
Also revokes all dependent grants
raj loses access too
Always succeeds
RESTRICT
Behaviour
Revokes the privilege
Refuses if dependents exist
raj's grant blocks it
Errors out, changes nothing
-- Cascade: amy AND everyone she granted to lose SELECT
REVOKE SELECT ON employees FROM analyst_amy CASCADE;

-- Restrict: fails with an error because raj still depends on amy's grant
REVOKE SELECT ON employees FROM analyst_amy RESTRICT;
🧮
Which Is the Default?

The SQL standard treats RESTRICT as the safe default — it refuses rather than silently cascading. But defaults vary by database (some require you to state CASCADE explicitly, others behave differently), so always write the keyword you mean rather than relying on the default.


Section 10

Common Mistakes

Over-granting
Handing out ALL PRIVILEGES or using PUBLIC when a single SELECT to one role would do. Violates least privilege.
Forgetting CASCADE effects
Revoking with CASCADE and unexpectedly cutting off downstream users who depended on the grant.
⚠️
TO vs FROM mix-up
GRANT uses TO; REVOKE uses FROM. Swapping them is a syntax error.
⚠️
WITH GRANT OPTION sprawl
Giving the grant option freely creates tangled dependency trees that are hard to audit and revoke cleanly.
Prefer roles
Grant to roles, not individuals, so permissions stay consistent and easy to change in one place.
Be explicit
State CASCADE or RESTRICT deliberately instead of relying on the engine's default.

Section 11

Practice Problems

Use the building/keys scenario — owner hr_admin, table employees, users analyst_amy, intern_raj, manager_mia.

🧠 Work These Out
Q1
Allow manager_mia to read and update employees. → GRANT SELECT, UPDATE ON employees TO manager_mia;
Q2
Let amy read employees and re-grant that right. → GRANT SELECT ON employees TO analyst_amy WITH GRANT OPTION;
Q3
Create a read-only role and give it to raj. → CREATE ROLE read_only; GRANT SELECT ON employees TO read_only; GRANT read_only TO intern_raj;
Q4
Remove amy's privilege and everything she granted from it. → REVOKE SELECT ON employees FROM analyst_amy CASCADE;
Q5
Stop amy re-granting, but let her keep reading. → REVOKE GRANT OPTION FOR SELECT ON employees FROM analyst_amy;
-- Q3 solution: role-based read-only access
CREATE ROLE read_only;
GRANT SELECT ON employees TO read_only;
GRANT read_only TO intern_raj;

Section 12

Golden Rules

🔑 DCL: GRANT & REVOKE — The Essentials
1
DCL has exactly two commands: GRANT (give a privilege, with TO) and REVOKE (take it back, with FROM).
2
Every privilege names an action, an object, and a grantee (user, role, or PUBLIC).
3
Follow least privilege: grant the minimum each user needs, and prefer object-level grants over ALL PRIVILEGES or PUBLIC.
4
WITH GRANT OPTION lets a grantee re-grant the privilege — convenient but it builds dependency chains that complicate revoking.
5
Use roles to bundle privileges: grant to the role once, assign the role to many users, and maintain permissions in a single place.
6
REVOKE … CASCADE also removes every dependent grant; RESTRICT refuses if dependents exist. State the keyword you mean explicitly.
7
Revoking a privilege from a role instantly affects every member; revoking from PUBLIC affects everyone who relied on it.
8
Use GRANT OPTION FOR to remove only the re-granting ability while leaving the underlying privilege intact.
You have completed SQL. View all sections →