INFORMIX
Informix Guide to SQL: Tutorial
Chapter 11: Granting and Limiting Access to Your Database
Home Contents Index Master Index New Book

Using Views

A view is a synthetic table. You can query it as if it were a table, and in some cases, you can update it as if it were a table. However, it is not a table. It is a synthesis of the data that exists in real tables and other views.

The basis of a view is a SELECT statement. When you create a view, you define a SELECT statement that generates the contents of the view at the time the view is accessed. A user also queries a view using a SELECT statement. The database server merges the SELECT statement of the user with the one defined for the view and then actually performs the combined statements.

The result has the appearance of a table; it is similar enough to a table that a view even can be based on other views, or on joins of tables and other views.

Because you write a SELECT statement that determines the contents of the view, you can use views for any of the following purposes:

  • To restrict users to particular columns of tables
    You name only permitted columns in the select list in the view.

  • To restrict users to particular rows of tables
    You specify a WHERE clause that returns only permitted rows.

  • To constrain inserted and updated values to certain ranges
    You can use the WITH CHECK OPTION (discussed on page 11-31) to enforce constraints.

  • To provide access to derived data without having to store redundant data in the database
    You write the expressions that derive the data into the select list in the view. Each time you query the view, the data is derived anew. The derived data is always up to date, yet no redundancies are introduced into the data model.

  • To hide the details of a complicated SELECT statement
    You hide complexities of a multitable join in the view so that neither users nor application programmers need to repeat them.

Creating Views

The following example creates a view based on a table in the stores7 database:

The view exposes only three columns of the table. Because it contains no WHERE clause, the view does not restrict the rows that can appear.

GLS
The following example creates a view based on a table that is available when a locale other than the default U.S. English locale using the ISO8859-1 code set has been enabled. In the example, the view, column, and table names contain non-English characters.

The following example is based on the join of two tables:

The table of state names reduces the redundancy of the database; it lets you store the full state names only once, which can be useful for long state names such as Minnesota. This full_addr view lets users retrieve the address as if the full state name were stored in every row. The following two queries are equivalent:

However, be careful when you define views that are based on joins. Such views are not modifiable; that is, you cannot use them with UPDATE, DELETE, or INSERT statements. (Modifying through views is covered beginning on page 11-29.)

The following example restricts the rows that can be seen in the view:

This view exposes all columns of the customer table, but only certain rows. The following example is a view that restricts users to rows that are relevant to them:

All the columns of the cust_calls table are available but only in those rows that contain the user IDs of the users who can execute the query.

Duplicate Rows from Views

A view might produce duplicate rows, even when the underlying table has only unique rows. If the view SELECT statement can return duplicate rows, the view itself can appear to contain duplicate rows.

You can prevent this problem in two ways. One way is to specify DISTINCT in the select list in the view. However, specifying DISTINCT makes it impossible to modify through the view. The alternative is to always select a column or group of columns that is constrained to be unique. (You can be sure that only unique rows are returned if you select the columns of a primary key or of a candidate key. Primary and candidate keys are discussed in Chapter 8, "Building Your Data Model.")

Restrictions on Views

Because a view is not really a table, it cannot be indexed, and it cannot be the object of such statements as ALTER TABLE and RENAME TABLE. The columns of a view cannot be renamed with RENAME COLUMN. To change anything about the definition of a view, you must drop the view and re-create it.

Because it must be merged with the user's query, the SELECT statement on which a view is based cannot contain any of the following clauses:

INTO TEMP

The user's query might contain INTO TEMP; if the view also contains it, the data would not know where to go.

UNION

The user's query might contain UNION. No meaning has been defined for nested UNION clauses.

ORDER BY

The user's query might contain ORDER BY. If the view also contains it, the choice of columns or sort directions could be in conflict.

When the Basis Changes

The tables and views on which a view is based can change in several ways. The view automatically reflects most of the changes.

When a table or view is dropped, any views in the same database that depend on it are automatically dropped.

The only way to alter the definition of a view is to drop and re-create it. Therefore, if you change the definition of a view on which other views depend, you must also re-create the other views (because they all have been dropped).

When a table is renamed, any views in the same database that depend on it are modified to use the new name. When a column is renamed, views in the same database that depend on that table are updated to select the proper column. However, the names of columns in the views themselves are not changed. For an example of this, recall the following view on the customer table:

Now suppose that the customer table is changed in the following way:

To select last names of customers directly, you must now select the new column name. However, the name of the column as seen through the view is unchanged. The following two queries are equivalent:

When you alter a table by dropping a column, views are not modified. If they are used, error -217 (Column not found in any table in the query) occurs. The reason views are not dropped is that you can change the order of columns in a table by dropping a column and then adding a new column of the same name. If you do this, views based on that table continue to work. They retain their original sequence of columns.

Universal Server permits you to base a view on tables and views in external databases. Changes to tables and views in other databases are not reflected in views. Such changes might not be apparent until someone queries the view and gets an error because an external table changed.

Creating Typed Views

You can create a typed view when you want to distinguish between two views that display data of the same data type. For example, suppose you want to create two views on the following table:

The following statements create two typed views, name_age and name_salary, on the emp table:

When you create a typed view, the data that the view displays is of a named row type. For example, the name_age and name_salary views contain VARCHAR and INTEGER data. Because the views are typed, a query against the name_age view returns a column view of type name_age whereas a query against the name_salary view returns a column view of type name_salary. Consequently, Universal Server is able to distinguish between rows that the name_age and name_salary views return.

In some cases, a typed view has a distinct advantage over an untyped view. For example, suppose you have overloaded a function foo(). Depending on the argument types that you specify, the database server calls a different function foo(). (For more information about function overloading, see Extending INFORMIX-Universal Server: User-Defined Routines.) Because the name_age and name_salary views are typed views, the following statements resolve to the appropriate foo() function, according to the type of the view that is associated with the alias p:

If two views that contain the same data types are not created as typed views, Universal Server cannot distinguish between the rows that the two views display.

Modifying Through a View

You can modify views as if they were tables. Some views can be modified and others not, depending on their SELECT statements. The restrictions are different, depending on whether you use DELETE, UPDATE, or INSERT statements.

No modification is possible on a view when its SELECT statement contains any of the following features:

  • A join of two or more tables
    Many anomalies arise if the database server tries to distribute modified data correctly across the joined tables.

  • An aggregate function or the GROUP BY clause
    The rows of the view represent many combined rows of data; the database server cannot distribute modified data into them.

  • The DISTINCT keyword or its synonym UNIQUE
    The rows of the view represent a selection from among possibly many duplicate rows; the database server cannot tell which of the original rows should receive the modification.

When a view avoids all these things, each row of the view corresponds to exactly one row of one table. Such a view is modifiable. (Of course, particular users can modify a view only if they have suitable privileges. Privileges on views are discussed beginning on page 11-32.)

Deleting Through a View

You can use a modifiable view with a DELETE statement as if it were a table. The database server deletes the proper row of the underlying table.

Updating a View

You can use a modifiable view with an UPDATE statement as if it were a table. However, a modifiable view can still contain derived columns; that is, columns that are produced by expressions in the select list of the CREATE VIEW statement. You cannot update derived columns (sometimes called virtual columns).

When a column is derived from a simple arithmetic combination of a column with a constant value (for example, order_date+30), the database server can, in principle, figure out how to invert the expression (in this case, by subtracting 30 from the update value) and perform the update. However, much more complicated expressions are possible, most of which cannot easily be inverted. Therefore, the database server does not support updating any derived column.

The following example shows a modifiable view that contains a derived column and an UPDATE statement that can be accepted against it:

The duration column of the view cannot be updated because it represents an expression (the database server cannot, even in principle, decide how to distribute an update value between the two columns named in the expression). But as long as no derived columns are named in the SET clause, the update can be performed as if the view were a table.

A view can return duplicate rows even though the rows of the underlying table are unique. You cannot distinguish one duplicate row from another. If you update one of a set of duplicate rows (for example, by using a cursor to update WHERE CURRENT), you cannot be sure which row in the underlying table receives the update.

Inserting into a View

You can insert rows into a view provided that the view is modifiable and contains no derived columns. The reason for the second restriction is that an inserted row must provide values for all columns, and the database server cannot tell how to distribute an inserted value through an expression. An attempt to insert into the call_response view, as the previous example shows, would fail.

When a modifiable view contains no derived columns, you can insert into it as if it were a table. However, the database server uses null as the value for any column that is not exposed by the view. If such a column does not allow nulls, an error occurs, and the insert fails.

Using the WITH CHECK OPTION Clause

You can insert into a view a row that does not satisfy the conditions of the view; that is, a row that is not visible through the view. You can also update a row of a view so that it no longer satisfies the conditions of the view.

To avoid updating a row of a view so that it no longer satisfies the conditions of the view, you can add the WITH CHECK OPTION clause when you create the view. This clause asks the database server to test every inserted or updated row to ensure that it meets the conditions set by the WHERE clause of the view. The database server rejects the operation with an error if the conditions are not met.

In the previous example, the view named call_response is defined as the following example shows:

You can update the user_id column of the view, as the following example shows:

The view requires rows in which user_id equals USER. If a user named tony performs this update, the updated rows vanish from the view. However, you can create the view as the following example shows:

The preceding update by tony is rejected as an error.

You can use the WITH CHECK OPTION clause to enforce any kind of data constraint that can be stated as a Boolean expression. In the following example, you can create a view of a table in which all the logical constraints on data are expressed as conditions of the WHERE clause. Then you can require all modifications to the table to be made through the view.

Because of EXISTS and other tests, which are expected to be successful when retrieving existing rows, this view displays data from orders inefficiently. However, if insertions to orders are made only through this view (and you are not already using integrity constraints to constrain data), users cannot insert a back-dated order, an invalid customer number, or an excessive shipping weight and shipping charge.




Informix Guide to SQL: Tutorial, version 9.1
Copyright © 1998, Informix Software, Inc. All rights reserved.