August 3, 2023
Summary: In this tutorial, we will show you how to create an updatable view using the WITH CHECK OPTION
clause to ensure that the changes to the base tables through the view satisfy the view-defining condition.
Table of Contents
Introduction to the WITH CHECK OPTION clause
In the creating updatable view tutorial, you have learned how to create an updatable view that allows you to change the data of the base table through the view.
Let’s take a look at the city
and country
tables in the sample database.
The following statement creates an updatable view named usa_city
that returns all cities in the Untied States.
CREATE VIEW usa_city AS SELECT
city_id,
city,
country_id
FROM
city
WHERE
country_id = 103
ORDER BY
city;
The following statement inserts a new row into the city
table through the usa_city.
INSERT INTO usa_city (city, country_id)
VALUES ('Birmingham', 102);
INSERT INTO usa_city (city, country_id)
VALUES ('Cambridge', 102);
The issue is that the new row inserted is not visible in the view. It may pose a security issue because we may grant the permission to the users to update the cities in the United States, not the United Kingdom.
To prevent users from the insert or update a row that not visible through the view, you use the WITH CHECK OPTION
clause when creating the view.
Let’s change the usa_city
view to include the WITH CHECK OPTION
clause
CREATE
OR REPLACE VIEW usa_city AS SELECT
city_id,
city,
country_id
FROM
city
WHERE
country_id = 103
ORDER BY
city WITH CHECK OPTION;
Now, run the following statement to insert another city for the United Kingdom
country.
PostgreSQL rejected the insert and issued an error.
ERROR: new row violates check option for view "usa_city"
DETAIL: Failing row contains (604, Cambridge, 102, 2016-07-02 08:41:01.828561).
It works as expected.
The following statement updates the country of the city id 135 to the United Kingdom
.
UPDATE usa_city
SET country_id = 102
WHERE
city_id = 135;
PostgreSQL rejected the update and issued an error.
ERROR: new row violates check option for view "usa_city"
DETAIL: Failing row contains (135, Dallas, 102, 2016-07-02 10:37:27.466176).
This is because the UPDATE statement causes the row that is being updated not visible through the usa_city
view.
The scope of check with LOCAL and CASCADED
First, create a view that returns all cities with the name starting with the letter A.
CREATE VIEW city_a AS SELECT
city_id,
city,
country_id
FROM
city
WHERE
city LIKE 'A%';
The city_a
view does not have the WITH CHECK OPTION
clause.
Second, create another view that returns the cities whose name starts with the letter A and locate in the United States
. This city_a_usa
view is based on the city_a
view.
CREATE
OR REPLACE VIEW city_a_usa AS SELECT
city_id,
city,
country_id
FROM
city_a
WHERE
country_id = 103
WITH CASCADED CHECK OPTION;
The city_a_usa
view has the WITH CASCADED CHECK OPTION
clause. Notice the CASCADED
option.
The following statement inserts a row into the city
table through the city_a_usa
table.
INSERT INTO city_a_usa (city, country_id)
VALUES
('Houston', 103);
PostgreSQL rejected the insert and issued the following error:
ERROR: new row violates check option for view "city_a"
SQL state: 44000
Detail: Failing row contains (605, Houston, 103, 2016-07-02 09:51:40.916855).
The error message indicates that the view-defining condition for the city_a
view was violated even though the city_a view does not have the WITH CHECK OPTION
clause.
This is because when we used the WITH CASCADED CHECK OPTION
for the city_a_usa
view, PostgreSQL checked the view-defining condition of the city_a_usa
view and also all the underlying views, in this case, it is the city_a view.
To check the view-defining condition of the view that you insert or update, you use the WITH LOCAL CHECK OPTION
as follows:
CREATE OR REPLACE VIEW city_a_usa AS SELECT
city_id,
city,
country_id
FROM
city_a
WHERE
country_id = 103
WITH LOCAL CHECK OPTION;
Let’s insert a new row into city table via the city_a_usa view again.
INSERT INTO city_a_usa (city, country_id)
VALUES
('Houston', 103);
It succeeded this time because the new row satisfies the view-defining condition of the city_a_usa
view. PostgreSQL did not check the view-defining conditions of the base views.
In this tutorial, you have learned how to create updatable views using the WITH CHECK OPTION
clause for checking the view-defining condition when making the changes to the underlying table through the view.