Regular Views
View declarations; query changes emit
CREATE OR REPLACE VIEW; output column list changes emit DROP VIEW CASCADE.The AS query clause is Part 1, terminated with ;. An optional { } block holds grants, comments, and the owner.
Basic view
SCHEMA public {
VIEW active_users AS
SELECT id, email, created_at
FROM users
WHERE status = 'active' AND deleted_at IS NULL;
}
-- emits
CREATE OR REPLACE VIEW "public"."active_users" AS
SELECT id, email, created_at
FROM users
WHERE status = 'active' AND deleted_at IS NULL;
View with explicit column aliases
VIEW user_summary (user_id, email, order_count) AS
SELECT u.id, u.email, COUNT(o.id)
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
GROUP BY u.id, u.email;
CREATE OR REPLACE VIEW "public"."user_summary" ("user_id", "email", "order_count") AS
SELECT u.id, u.email, COUNT(o.id)
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
GROUP BY u.id, u.email;
View with security_barrier
VIEW secure_user_view WITH (security_barrier = true) AS
SELECT id, email FROM users WHERE tenant_id = current_tenant();
CREATE VIEW "public"."secure_user_view" WITH (security_barrier=true) AS SELECT id, email FROM users WHERE tenant_id = current_tenant();
security_invoker works the same way. An option written without a value, such as WITH (security_barrier), means true.
View with WITH CHECK OPTION
VIEW active_orders AS
SELECT * FROM orders WHERE status != 'cancelled'
WITH LOCAL CHECK OPTION;
CREATE VIEW "public"."active_orders" WITH (check_option=local) AS SELECT * FROM orders WHERE status <> 'cancelled';
PostgreSQL stores WITH [LOCAL | CASCADED] CHECK OPTION as the view option check_option, so DPG writes it that way. Writing WITH (check_option = local) yourself means the same thing.
View with grants and comment
VIEW admin_summary AS
SELECT id, email, created_at FROM users WHERE role = 'admin' {
COMMENT 'Admin user summary';
GRANTS { SELECT TO app_readonly; }
}
CREATE OR REPLACE VIEW "public"."admin_summary" AS
SELECT id, email, created_at FROM users WHERE role = 'admin';
COMMENT ON VIEW "public"."admin_summary" IS 'Admin user summary';
GRANT SELECT ON "public"."admin_summary" TO "app_readonly";
Diffing behaviour
| Change | SQL emitted | Safety |
|---|---|---|
| Query body changes; output column list unchanged | CREATE OR REPLACE VIEW, restating the view’s options (PostgreSQL resets any it omits) | SAFE |
| View options or check option change; query unchanged | ALTER VIEW ... SET (...) / RESET (...) | CAUTION |
| Output column list changes in any way | DROP VIEW CASCADE then CREATE VIEW | DESTRUCTIVE |