The Story That Explains DCL
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.
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.
Where DCL Sits Among SQL Commands
SQL statements fall into four families. DCL is one of them — the one concerned purely with permissions.
Two Kinds of Privileges
SELECT, INSERT,
UPDATE, DELETE, REFERENCES, EXECUTE.
CREATE TABLE, CREATE USER,
CREATE SESSION, DROP ANY TABLE, and similar administrative rights.
| Object privilege | Lets the user… |
|---|---|
SELECT | read rows from the table or view |
INSERT | add new rows (can be limited to specific columns) |
UPDATE | modify existing rows (can be column-specific) |
DELETE | remove rows |
REFERENCES | create a foreign key that points at the table |
EXECUTE | run a stored procedure or function |
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;
The privilege token travels from the owner to the grantee; once it arrives, the grantee's box turns green and the access is live.
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.
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;
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.
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;
hr_staff documents intent far better than a scattered list of grants.
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;
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.
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;
| Property |
|---|
Keyword TO |
| Gives a privilege |
Optional WITH GRANT OPTION |
| Opens access |
| Property |
|---|
Keyword FROM |
| Removes a privilege |
Optional CASCADE / RESTRICT |
| Closes access |
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.
Because raj's access was derived from amy's, CASCADE revokes raj's privilege automatically. The owner is unaffected.
| Behaviour |
|---|
| Revokes the privilege |
| Also revokes all dependent grants |
| raj loses access too |
| Always succeeds |
| 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;
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.
Common Mistakes
ALL PRIVILEGES or using PUBLIC when a single SELECT to one role would do. Violates least privilege.CASCADE and unexpectedly cutting off downstream users who depended on the grant.TO; REVOKE uses FROM. Swapping them is a syntax error.CASCADE or RESTRICT deliberately instead of relying on the engine's default.Practice Problems
Use the building/keys scenario — owner hr_admin, table employees, users analyst_amy, intern_raj, manager_mia.
GRANT SELECT, UPDATE ON employees TO manager_mia;
GRANT SELECT ON employees TO analyst_amy WITH GRANT OPTION;
CREATE ROLE read_only; GRANT SELECT ON employees TO read_only; GRANT read_only TO intern_raj;
REVOKE SELECT ON employees FROM analyst_amy CASCADE;
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;
Golden Rules
GRANT (give a privilege, with
TO) and REVOKE (take it back, with FROM).
PUBLIC).
ALL PRIVILEGES or PUBLIC.
WITH GRANT OPTION lets a grantee re-grant the privilege — convenient but it
builds dependency chains that complicate revoking.
REVOKE … CASCADE also removes every dependent grant;
RESTRICT refuses if dependents exist. State the keyword you mean explicitly.
PUBLIC affects everyone who relied on it.
GRANT OPTION FOR to remove only the re-granting ability while leaving the
underlying privilege intact.