CREATE MATERIALIZED VIEW
Applies to: Databricks SQL
A materialized view is a view where precomputed results are available for query and can be updated to reflect changes in the input. Each time a materialized view is refreshed, query results are recalculated to reflect changes in upstream datasets. All materialized views are backed by a DLT pipeline. You can refresh materialized views manually or on a schedule.
To learn more about how to perform a manual refresh, see REFRESH (MATERIALIZED VIEW or STREAMING TABLE).
To learn more about how to schedule a refresh, see Examples or ALTER MATERIALIZED VIEW.
Note
Create and refresh operations on materialized views and streaming tables are powered by a serverless Delta Live Tables pipeline. You can use Catalog Explorer to view details about the backing pipelines in the UI. See What is Catalog Explorer?.
Syntax
{ CREATE OR REPLACE MATERIALIZED VIEW | CREATE MATERIALIZED VIEW [ IF NOT EXISTS ] }
view_name
[ column_list ]
[ view_clauses ]
[schedule_clause]
AS query
column_list
( { column_name column_type column_properties } [, ...]
[ , table_constraint ] [...])
column_properties
{ NOT NULL | COMMENT column_comment | column_constraint | MASK clause } [ ... ]
view_clauses
{ PARTITIONED BY (col [, ...]) |
COMMENT view_comment |
TBLPROPERTIES clause |
SCHEDULE [ REFRESH ] schedule_clause |
WITH { ROW FILTER clause } } [...]
schedule_clause
{ EVERY number { HOUR | HOURS | DAY | DAYS | WEEK | WEEKS } |
CRON cron_string [ AT TIME ZONE timezone_id ] }
Parameters
REPLACE
If specified, replaces the view and its content if it already exists.
IF NOT EXISTS
Creates the view if it does not exist. If a view by this name already exists, the
CREATE MATERIALIZED VIEW
statement is ignored.You may specify at most one of
IF NOT EXISTS
orOR REPLACE
.-
The name of the newly created view. The fully qualified view name must be unique.
column_list
Optionally labels the columns in the query result of the view. If you provide a column list the number of column aliases must match the number of expressions in the query. If no column list is specified, aliases are derived from the body of the view.
-
The column names must be unique and map to the output columns of the query.
column_type
Specifies the column’s data type. Not all data types supported by Databricks are supported by materialized views.
column_comment
An optional
STRING
literal describing the column. This option must be specified along withcolumn_type
. If the column type is not specified, the column comment is skipped.column_constraint
Adds an informational primary key or informational foreign key constraint to the column in a materialized view. If the column type is not specified, the column constraint is skipped.
-
Preview
This feature is in Public Preview.
Adds a column mask function to anonymize sensitive data. All subsequent queries from that column receive the result of evaluating that function over the column in place of the column’s original value. This can be useful for fine-grained access control purposes where the function can inspect the identity or group memberships of the invoking user to determine whether to redact the value. If the column type is not specified, the column mask is skipped.
-
table_constraint
Adds an informational primary key or informational foreign key constraint to the table in a materialized view. If the column type is not specified, the table constraint is skipped.
view_clauses
Optionally specify partitioning, comments, user defined properties, and a refresh schedule for the new materialized view. Each sub clause may only be specified once.
-
An optional list of columns of the table to partition the table by.
COMMENT view_comment
A
STRING
literal to describe the table.-
Optionally sets one or more user defined properties.
Use this setting to specify the Delta Live Tables runtime channel used to run this statement. Set the value of the
pipelines.channel
property to"PREVIEW"
or"CURRENT"
. The default value is"CURRENT"
. For more information about Delta Live Tables channels, see Delta Live Tables runtime channels. SCHEDULE [ REFRESH ] schedule_clause
EVERY number { HOUR | HOURS | DAY | DAYS | WEEK | WEEKS }
Preview
This feature is in Public Preview.
To schedule a refresh that occurs periodically, use
EVERY
syntax. IfEVERY
syntax is specified, the streaming table or materialized view is refreshed periodically at the specified interval based on the provided value, such asHOUR
,HOURS
,DAY
,DAYS
,WEEK
, orWEEKS
. The following table lists accepted integer values fornumber
.Time unit
Integer value
HOUR or HOURS
1 <= H <= 72
DAY or DAYS
1 <= D <= 31
WEEK or WEEKS
1 <= W <= 8
Note
The singular and plural forms of the included time unit are semantically equivalent.
CRON cron_string [ AT TIME ZONE timezone_id ]
To schedule a refresh using a quartz cron value. Valid time_zone_values are accepted.
AT TIME ZONE LOCAL
is not supported.If
AT TIME ZONE
is absent, the session time zone is used. IfAT TIME ZONE
is absent and the session time zone is not set, an error is thrown.SCHEDULE
is semantically equivalent toSCHEDULE REFRESH
.
WITH ROW FILTER clause
Preview
This feature is in Public Preview.
Adds a row filter function to the table. All subsequent queries from that table receive a subset of the rows for which the function evaluates to boolean TRUE. This can be useful for fine-grained access control purposes where the function can inspect the identity or group memberships of the invoking user to determine whether to filter certain rows.
-
AS query
A query that constructs the view from base tables or other views.
Required permissions
The user who creates a materialized view (MV) is the MV owner and needs to have the following permissions:
SELECT
privilege over the base tables referenced by the MV.USE CATALOG
privilege on the parent catalog and theUSE SCHEMA
privilege on the parent schema.CREATE MATERIALIZED VIEW
privilege on the schema for the MV.
For a user to be able to refresh the MV, they require:
USE CATALOG
privilege on the parent catalog and theUSE SCHEMA
privilege on the parent schema.Ownership of the MV or
REFRESH
privilege on the MV.The owner of the MV must have the
SELECT
privilege over the base tables referenced by the MV.
For a user to be able to query the MV, they require:
USE CATALOG
privilege on the parent catalog and theUSE SCHEMA
privilege on the parent schema.SELECT
privilege over the materialized view.
Row filters and column masks
Preview
This feature is in Public Preview.
Row filters let you specify a function that applies as a filter whenever a table scan fetches rows. These filters ensure that subsequent queries only return rows for which the filter predicate evaluates to true.
Column masks let you mask a column’s values whenever a table scan fetches rows. All future queries involving that column will receive the result of evaluating the function over the column, replacing the column’s original value.
For more information on how to use row filters and column masks, see Filter sensitive table data using row filters and column masks.
Managing Row Filters and Column Masks
Row filters and column masks on materialized views should be added through the CREATE
statement.
Behavior
Refresh as Definer: When the
REFRESH MATERIALIZED VIEW
statement refreshes a materialized view, row filter functions run with the definer’s rights (as the table owner). This means the table refresh uses the security context of the user who created the materialized view.Query: While most filters run with the definer’s rights, functions that check user context (such as
CURRENT_USER
andIS_MEMBER
) are exceptions. These functions run as the invoker. This approach enforces user-specific data security and access controls based on the current user’s context.When creating materialized views over source tables that contain row filters and column masks, the refresh of the materialized view is always a full refresh. A full refresh reprocesses all data available in the source with the latest definitions. This ensures that security policies on the source tables are evaluated and applied with the most up-to-date data and definitions.
Limitations
When a materialized view with a
sum
aggregate over a NULL-able column has the last non-NULL value removed from that column - and thus onlyNULL
values remain in that column - the materialized view’s resultant aggregate value returns zero instead ofNULL
.Column-reference does not require an alias. Non-column reference expressions require an alias, as in the following example:
Allowed:
SELECT col1, SUM(col2) AS sum_col2 FROM t GROUP BY col1
Not Allowed:
SELECT col1, SUM(col2) FROM t GROUP BY col1
NOT NULL
must be manually specified along withPRIMARY KEY
in order to be a valid statement.Materialized views do not support identity columns or surrogate keys.
Materialized views do not support
OPTIMIZE
andVACUUM
commands. Maintenance happens automatically.Materialized views do not support expectations to define data quality constraints.
Examples
-- Create a materialized view if it doesn't exist
> CREATE MATERIALIZED VIEW IF NOT EXISTS subscribed_movies
AS SELECT mo.member_id, mb.full_name, mo.movie_title
FROM movies AS mo INNER JOIN members AS mb ON mo.member_id = mb.id;
-- Create and schedule a materialized view to be refreshed daily at midnight.
-- Note: All columns in a GROUP BY need to be explicitly aliased
> CREATE MATERIALIZED VIEW daily_sales
COMMENT 'Daily sales numbers'
SCHEDULE CRON '0 0 0 * * ? *'
AS SELECT date AS date, sum(sales) AS sumOfSales
FROM table1
GROUP BY date;
-- Sets the runtime channel to "PREVIEW"
> CREATE MATERIALIZED VIEW mv_preview
TBLPROPERTIES(pipelines.channel = "PREVIEW")
AS SELECT * FROM RANGE(10)
-- Create a materialized view with a table constraint
> CREATE MATERIALIZED VIEW IF NOT EXISTS subscribed_movies(
member_id int NOT NULL,
full_name string,
movie_title string,
CONSTRAINT movie_pk PRIMARY KEY(member_id)
)
AS SELECT mo.member_id, mb.full_name, mo.movie_title
FROM movies AS mo INNER JOIN members AS mb ON mo.member_id = mb.id;
-- Create or replace the materialized view to remove the table constraint and add a partition
> CREATE OR REPLACE MATERIALIZED VIEW subscribed_movies
PARTITIONED BY (member_id)
AS SELECT mo.member_id, mb.full_name, mo.movie_title
FROM movies AS mo INNER JOIN members AS mb ON mo.member_id = mb.id;
-- Create a materialized view with a row filter and a column mask
> CREATE MATERIALIZED VIEW masked_view (
id int,
name string,
region string,
ssn string MASK catalog.schema.ssn_mask_fn
)
WITH ROW FILTER catalog.schema.us_filter_fn ON (region)
AS SELECT id, name, region, ssn
FROM employees;