Oracle Updatable View

Summary: in this tutorial, you will learn about Oracle’s updatable view and how to insert or update data in the base tables through a view.

Introduction to Oracle Updatable View

A view behaves like a table because you can query data from it. However, you cannot always manipulate data via views. A view is updatable if the statement against the view can be translated into the corresponding statement against the underlying table.

Let’s consider the following database tables:

Oracle Updatable View - Sample Tables

In a database diagram, a car belongs to one brand while a brand has one or many cars. The relationship between brand and car is one-to-many.

The following SQL statements create the cars and brands tables; and also insert sample data into these tables.

CREATE TABLE brands(
	brand_id NUMBER GENERATED BY DEFAULT AS IDENTITY,
	brand_name VARCHAR2(50) NOT NULL,
	PRIMARY KEY(brand_id)
);

CREATE TABLE cars (
	car_id NUMBER GENERATED BY DEFAULT AS IDENTITY,
	car_name VARCHAR2(255) NOT NULL,
	brand_id NUMBER NOT NULL,
	PRIMARY KEY(car_id),
	FOREIGN KEY(brand_id) 
	REFERENCES brands(brand_id) ON DELETE CASCADE
);

INSERT INTO brands(brand_name)
VALUES('Audi');

INSERT INTO brands(brand_name)
VALUES('BMW');

INSERT INTO brands(brand_name)
VALUES('Ford');

INSERT INTO brands(brand_name)
VALUES('Honda');

INSERT INTO brands(brand_name)
VALUES('Toyota');

INSERT INTO cars (car_name,brand_id)
VALUES('Audi R8 Coupe',1);

INSERT INTO cars (car_name,brand_id)
VALUES('Audi Q2', 1);

INSERT INTO cars (car_name,brand_id)
VALUES('Audi S1', 1);

INSERT INTO cars (car_name,brand_id)
VALUES('BMW 2-serie Cabrio',2);

INSERT INTO cars (car_name,brand_id)
VALUES('BMW i8', 2);

INSERT INTO cars (car_name,brand_id)
VALUES('Ford Edge',3);

INSERT INTO cars (car_name,brand_id)
VALUES('Ford Mustang Fastback', 3);

INSERT INTO cars (car_name,brand_id)
VALUES('Honda S2000', 4);

INSERT INTO cars (car_name,brand_id)
VALUES('Honda Legend', 4);

INSERT INTO cars (car_name,brand_id)
VALUES('Toyota GT86', 5);

INSERT INTO cars (car_name,brand_id)
VALUES('Toyota C-HR', 5);Code language: SQL (Structured Query Language) (sql)

Oracle updatable view example

The following statement creates a new view named cars_master:

CREATE VIEW cars_master AS 
SELECT
    car_id,
    car_name
FROM
    cars;
Code language: SQL (Structured Query Language) (sql)

It’s possible to delete a row from the cars table via the cars_master view, for example:

DELETE
FROM
    cars_master
WHERE
    car_id = 1;
Code language: SQL (Structured Query Language) (sql)

You can update any column values exposed to the cars_master view:

UPDATE
    cars_master
SET
    car_name = 'Audi RS7 Sportback'
WHERE
    car_id = 2;
Code language: SQL (Structured Query Language) (sql)

We could insert and update data from the cars table via cars_master view because Oracle can translate the INSERT and UPDATE statements to the corresponding statements and execute them against the cars table.

However, insert a new row into the cars table via the cars_master view is not possible. Because the cars table has a not null column ( brand_id) without a default value.

INSERT INTO cars_master
VALUES('Audi S1 Sportback');Code language: SQL (Structured Query Language) (sql)

Oracle issued an error:

SQL Error: ORA-00947: not enough valuesCode language: SQL (Structured Query Language) (sql)

Oracle updatable join view example

Let’s create a join view named all_cars based on the cars and brands tables.

CREATE VIEW all_cars AS 
SELECT
    car_id,
    car_name,
    c.brand_id,
    brand_name
FROM
    cars c
INNER JOIN brands b ON
    b.brand_id = c.brand_id; 
Code language: SQL (Structured Query Language) (sql)

The following statement inserts a new row into the cars table via the call_cars view:

INSERT INTO all_cars(car_name, brand_id )
VALUES('Audi A5 Cabriolet', 1);
Code language: SQL (Structured Query Language) (sql)

A new row has been inserted into the cars table. This INSERT statement works because Oracle can decompose it to an INSERT statement against the cars table.

The following statement deletes all Honda cars from the cars table via the all_cars view:

DELETE
FROM
    all_cars
WHERE
    brand_name = 'Honda';
Code language: JavaScript (javascript)

2 rows deleted.

Oracle has some rules and restrictions that apply to updatable join views. One of them is the concept of key-preserved tables.

A key-preserved table is a base table with a one-to-one row relationship with the rows in the view, via either the primary key or a unique key. In the example above, the cars table is a key-preserved table.

Here are some examples of updatable join view restrictions:

  • The SQL statement e.g., INSERT, UPDATE, and DELETE, is only allowed to modify data from a single base table.
  • For an INSERT statement, all columns listed in the INTO clause must belong to a key-preserved table.
  • For an UPDATE statement, all columns in the SET clause must belong to a key-preserved table.
  • For a DELETE statement, if the join results in more than one key-preserved table, the Oracle deletes from the first table in the FROM clause.

Besides these restrictions, Oracle also requires that the defining query does not contain any of the following elements:

Find updatable columns of a join view

To find which column can be updated, inserted, or deleted, you use the user_updatable_columns view. The following example shows which column of the all_cars view is updatable, insertable, and deletable:

SELECT
    *
FROM
    USER_UPDATABLE_COLUMNS
WHERE
    TABLE_NAME = 'ALL_CARS';Code language: SQL (Structured Query Language) (sql)
Oracle Updatable Join view

In this tutorial, you have learned about the Oracle updatable view and how to update underlying base tables through it.

Was this tutorial helpful?