Views
Learn what views are and when to use them.
Views sit on top of the tables you create in Tables and data.
A view is a convenient shortcut to a query. Creating a view doesn't involve new tables or data. When you run a view, Postgres executes the underlying query and returns its results.
Say you have the following tables from a university database:
students
| id | name | type |
|---|---|---|
| 1 | Princess Leia | undergraduate |
| 2 | Yoda | graduate |
| 3 | Anakin Skywalker | graduate |
courses
| id | title | code |
|---|---|---|
| 1 | Introduction to Postgres | PG101 |
| 2 | Authentication Theories | AUTH205 |
| 3 | Fundamentals of Supabase | SUP412 |
grades
| id | student_id | course_id | result |
|---|---|---|---|
| 1 | 1 | 1 | B+ |
| 2 | 1 | 3 | A+ |
| 3 | 2 | 2 | A |
| 4 | 3 | 1 | A- |
| 5 | 3 | 2 | A |
| 6 | 3 | 3 | B- |
Creating a view that consists of all three tables looks like this:
create view transcripts as select students.name, students.type, courses.title, courses.code, grades.result from grades left join students on grades.student_id = students.id left join courses on grades.course_id = courses.id;grant all on table transcripts to authenticated;Then you can access the underlying query with:
select * from transcripts;View security#
By default, views are accessed with their creator's permission, known as security definer. If a privileged role creates a view, others accessing it use that role's elevated permissions. To enforce row level security policies, define the view with the security_invoker modifier.
-- alter a security_definer view to be security_invokeralter view <view name>set (security_invoker = true);-- create a view with the security_invoker modifiercreate view <view name> with(security_invoker=true) as ( select * from <some table>);When to use views#
Views provide several benefits.
Simplicity#
As a query becomes more complex, calling it repeatedly gets tedious, especially when you run it regularly. In the example above, instead of repeatedly running:
select students.name, students.type, courses.title, courses.code, grades.resultfrom grades left join students on grades.student_id = students.id left join courses on grades.course_id = courses.id;You can run this instead:
select * from transcripts;A view also behaves like a typical table. You can safely use it in table joins or create new views from existing views.
Consistency#
Views reduce the likelihood of mistakes when you execute a query repeatedly. In the example above, you might decide to exclude the course Introduction to Postgres. The query becomes:
select students.name, students.type, courses.title, courses.code, grades.resultfrom grades left join students on grades.student_id = students.id left join courses on grades.course_id = courses.idwhere courses.code != 'PG101';Without a view, you need to add the new rule to every dependent query. That increases the likelihood of errors and inconsistencies, and it takes considerable effort. With views, you alter the underlying query in the transcripts view, and the change applies to every application using it.
Logical organization#
With views, you can give your query a name. This is useful for teams working with the same database. Instead of guessing what a query does, a well-named view explains it. For example, the name of the transcripts view suggests that the underlying query involves the students, courses, and grades tables.
Security#
Views can restrict the amount and type of data presented to a user. Instead of giving a user direct access to a set of tables, you give them a view. You can prevent them from reading sensitive columns by excluding those columns from the underlying query.
Materialized views#
A materialized view is a form of view that also stores its results to disk. Subsequent reads of a materialized view return results much faster than a conventional view, because the data is already available. A conventional view executes the underlying query each time you call it.
Using the example above, you can create a materialized view like this:
create materialized view transcripts as select students.name, students.type, courses.title, courses.code, grades.result from grades left join students on grades.student_id = students.id left join courses on grades.course_id = courses.id;Reading from the materialized view is the same as a conventional view:
select * from transcripts;Refreshing materialized views#
There's a trade-off: data in a materialized view isn't always up to date. Refresh it regularly to prevent the data from becoming too stale.
refresh materialized view transcripts;How often you refresh a materialized view is up to you, and it probably differs for each view depending on its use case.
Materialized views vs conventional views#
Materialized views are useful when execution times for queries or views are too slow. This happens in views or queries that involve multiple tables and billions of rows. Use a materialized view only when you can tolerate outdated data. Internal dashboards and analytics are common use cases.
Creating a materialized view isn't a solution to inefficient queries. Always optimize a slow-running query, even when you implement a materialized view.