822.TXT
     =====================================================================
     Using Views
     =====================================================================
     PRODUCT:   R:BASE                 VERSION:  4.5 or Higher
     =====================================================================
     CATALOG:   Programming in R:BASE  AREA   :  Logic & Data Manipulation
     =====================================================================
 
     Views are powerful and useful database tools. A view is a stored
     SELECT command. No data is stored with a view; when a view is used,
     the data is dynamically generated so it is always current. Users
     often comment that they don't use views, or can't get them to work
     correctly, this article shows how easy views are to use and how
     useful they can be.
 
     A good relational database design almost always requires the use of
     views. Descriptive information is commonly stored in only one table,
     and related to other data through linking columns. For example, the
     invoice table won't store the employee name, rather it stores the
     employee id number. The employee name is looked up when needed or
     joined with the invoice table through a view.
 
     Views are commonly used to generate reports, manipulate data, and
     provide answers to queries not possible with a single SELECT command.
     A view can be based on one table or many tables, and can even use
     other views. Views are created using Query by Example (QBE) or the
     CREATE VIEW command in the R> prompt window.
 
     Using QBE to Create a View
     When you create a view using QBE, the menus prompt you through
     selecting the tables and the columns to display. You can view the
     data to make sure the query retrieves the desired data, then save the
     query as a view. The next time you want to look at that set of data,
     open the view from the Object Manager. The current data set is
     retrieved from the underlying tables and displayed in the Data
     Browser. Views created in QBE link the tables using the equals (=)
     operator and common column names by default. Other links can be
     created by changing QBE User Settings or by modifying the WHERE clause
     in the Where Builder. When you create a query using QBE, R:BASE builds
     a SELECT command with a WHERE clause to link the tables and identify
     the rows to display. That SELECT command is saved as the view
     definition.
 
     R:BASE 5.5 provides more query options through QBE than prior versions
     of R:BASE. You can even edit the WHERE clause in the Where Builder to
     create more complex queries, such as a query using a GROUP BY clause.
     This option is not available in DOS versions of R:BASE.
 
     Using the CREATE VIEW Command
     Not all queries can be defined using QBE. The R> prompt window
     provides a wider range of query options than does QBE. When creating
     a view from the R> prompt, first use the SELECT command to create and
     verify the query, then modify the SELECT command by adding the
     command string CREATE VIEW viewname AS to the front of the query.
     Here's an example of testing a query, then editing the command and
     creating a view.
 
     1. At the "R> Prompt" window, enter the command
 
     SELECT Customer.company, T1.custid, T1.transid, +
     T1.transdate, T1.invoicetotal +
     FROM Customer , TransMaster T1 +
     WHERE  T1.custid = Customer.custid
 
     Verify that the correct data is displayed.
 
     2. Press [PgUp] to retrieve the SELECT command. [PgUp] and [PgDn]
     cycle through the keyboard buffer of previously executed commands.
 
     3. Press [Home] to move to the beginning of the command.
 
     4. Turn insert mode on if it is not already on. Then, type "CREATE
     VIEW testview" and press the spacebar. The command now looks like
     this:
 
     CREATE VIEW v_trans AS +
       SELECT Customer.company, T1.custid, T1.transid, +
       T1.transdate, T1.invoicetotal +
       FROM Customer , TransMaster T1 +
       WHERE  T1.custid = Customer.custid
 
     5. Press [End] to move to the end of the command, then press [Enter]
     to execute the edited SELECT command and create the view.
 
     This technique is especially useful when working on complex views as
     you do not need to continually drop and create the view definition.
     Since a view is just a stored SELECT command, once the SELECT
     command works correctly it can be saved as a view using this
     technique.
 
     Table Relationships
     A view can be created to select data from one table or from many
     tables. A view can also retrieve data from other views. When a view is
     designed to retrieve data from many tables, the tables are joined. The
     data retrieved is determined by the relationship between the tables. A
     relationship is defined by the linking columns, which are columns that
     are from different tables and contain matching data. Linking columns
     often have the same name in both tables. There are three basic
     relationships between tables in a relational database:
 
       One-to-one_there is only one row in each table where the
       linking column(s) contain matching data. The linking
       column in each table is unique. When two tables with a
       one-to-one relationship are joined, the result is a "one"
       table.
       One-to-many_in one of the tables, the linking column is
       unique, there is only one row for each value. In the
       other table, there can be one row or many rows for the
       linking column. When the tables are joined, the result is
       a "many" table. The number of rows returned is the number
       of rows from the "many" table.
       Many-to-many_in both tables, there can be many rows for
       the linking column(s). The linking column value is not
       unique in either table. The result of a join between two
       "many" tables is a "many" table. The number of rows
       returned is the number of rows in one table multiplied by
       the number of rows in the other table.
 
     Relationships are usually defined between two tables at a time.
     Relationships between more than two tables are more easily defined
     when taken two at a time. For example, a one- to-many-to-many join
     can be thought of as a one-to-many join and then a many-to-many join.
 
     The one-to-many is the most common relationship in a relational
     database. For example, the relationship between customers and orders
     is a one-to-many relationship. Each customer has a row of data in
     a customer table, but can have many associated rows in an orders
     table. An example of a many-to-many relationship is the relationship
     between orders and payments. An order can have many payments
     associated with it, and a payment can be associated with many
     orders. When orders and payments are connected to customers, the
     relationship becomes a one-to-many-to-many. Each customer has a row of
     data in a customer table, many associated rows in an orders table, and
     many associated rows in a payments table. The payments and orders are
     both associated to the customer, but not necessarily to each other.
 
     Views are easy to create on one-to-one or one-to-many relationships.
     It is difficult to create a view on tables with a many-to-many or
     one-to-many-to-many relationship. Data is often duplicated or appears
     to be duplicated. Sometimes, intermediate views can be used to
     manipulate the data so that the view ends up with only one many table
     in the final result.
 
     Joining Tables
     The table relationships are used when joining tables. There are three
     types of joins_inner join, outer join, and self join. The most common
     way to join tables is to use an inner join, also called an equi-join.
     An inner join links the tables where the data in the linking column
     matches. When you create a view in QBE using one of the default
     WHERE clause options you create a view that is an inner join_only
     matching rows of data are retrieved.
 
     An outer join is also common, but is not created in QBE. An outer
     join view_a view where you retrieve all the matching rows between two
     tables and all the non-matching rows_must be created from the R>
     prompt window. The SELECT command includes a special syntax for
     creating outer joins. A view made using the outer join syntax of the
     SELECT command uses only two tables at a time. To join more than two
     tables using this syntax, you create multiple views.
 
     A self join, in which a table is joined to itself, is not commonly
     used. A self-join is usually created at the R> prompt.
 
     Naming the Columns in a View
     A view can be thought of as defining the structure for a temporary
     table. Each item specified for display in the SELECT command becomes
     a column. If you do not specify names for the items, R:BASE generates
     default names. If the item selected is a column, the default name is
     the column. If the item selected is an expression, the default name
     is the first part of the expression definition or just UNNAMED.
     Expressions do not generate a name that can be used to select this
     item in a report or a WHERE clause.
 
     You can explicitly name the columns in your view. This is an optional
     part of the CREATE VIEW syntax. Naming the columns is required on
     views that use expressions. In QBE you name the columns in your view
     by choosing Query: columns Aliases..... (available in R:BASE 5.5
     only). You can name the columns for any view created at the R>
     prompt.
 
     For example, create view v_trans1 with an expression but without
     explicit column names:
 
     CREATE VIEW v_trans1 AS +
       SELECT transid,SUM (extprice) +
       FROM transdetail T1,transmaster T2 +
       GROUP BY transid
 
     Selecting from the view displays the data as shown below. Notice
     that the first part of the expression becomes a column heading:
 
      transid    SUM (extprice)
      ---------- ---------------
            4780     $665,000.00
            4790   $3,972,500.00
            4795  $12,320,000.00
            4800  $13,632,500.00
 
     Change the view definition to use explicit column names. The column
     names can be the same as columns selected from the tables or they can
     be different. They are used for this view definition only. If you use
     a name that exists in another table or view in the database, the data
     type of the data in the column must match.
 
     CREATE VIEW v_trans2 (ID#,amount) AS +
       SELECT transid,SUM (extprice) +
       FROM transdetail T1,transmaster T2 +
       GROUP BY transid
 
     Now select the data from the view; the column headings reflect the
     names specified in the view definition. The expression is now named
     and can be referenced in a form, report, WHERE clause, or ORDER BY
     clause.
 
      ID#        amount
      ---------- ---------------
            4780     $665,000.00
            4790   $3,972,500.00
            4795  $12,320,000.00
            4800  $13,632,500.00
 
     When naming columns in a view, you can't just name the expressions;
     you must provide a name for each item that is selected. If there are
     five items selected for display, you must provide five column names
     when you create the view.
 
     Modifying a View Definition
     Views created in QBE can be modified in QBE. Some views created at
     the R> prompt can also be modified in QBE_views that could have been
     created in QBE. Normally, however, views created at the R> prompt
     cannot be modified in QBE. You will usually get the message "Internal
     Error - Out of Dynamic Space" when the view cannot be modified in QBE.
 
     To modify a view outside of QBE, follow these steps:
 
     1.Use the UNLOAD command to place the CREATE VIEW command for the
     view definition in a file.
 
          OUTPUT view.str
          UNLOAD STRUCTURE FOR v_trans
          OUTPUT SCREEN
 
     2.Edit the file using the R:BASE text editor or another ASCII text
     editor and modify the view definition as desired.
 
          RBEDIT view.str
 
     3.Remove the current view definition.
 
          DROP VIEW v_trans
 
     4.Re-create the view using the modified view definition.
 
          RUN view.str
 
     Some users always create their views using command files. You can
     easily incorporate the drop and create view commands into a command
     file, then just edit that command file to change a view definition.
     For example, the file v_trans.cmd might contain these commands:
 
     DROP VIEW v_trans
     CREATE VIEW v_trans (ID#,amount) AS +
       SELECT transid,SUM (extprice) +
       FROM transdetail +
       GROUP BY transid
 
     To modify the definition of the view v_trans, edit and then run the
     file v_trans.cmd. This type of command file is best run in
     single-user; in multi-user you cannot drop the view unless you can
     get a full database lock.
 
     Using Variables in Views
     Sometimes you want a view to retrieve rows based on different
     criteria, but don't want to always drop and re-create the view
     definition in order to change the WHERE clause. You can use a variable
     in the WHERE clause of your view definition or you can use a variable
     in an expression that is part of the view definition. The variable
     must exist in memory any time the view is created. The R:BASE BACKUP
     and RESTORE commands require that the variable be defined (exist in
     memory) when restoring the view definition.
 
     In the WHERE clause, put the variable name in parentheses, (.varname),
     so that the variable name, not the variable value, becomes part of the
     view definition. If the variables in the view definition are not
     enclosed in parentheses, their current value becomes part of the view
     definition. For example, the following commands create a view with the
     literal values for the date variables as part of the view definition:
 
     SET VAR vdate1 DATE = 9/1/95, vdate2 DATE = 9/30/95
     CREATE VIEW v_trans (transid, amount) AS +
       SELECT transid,SUM (extprice) +
       FROM transdetail T1, transmaster T2 +
       WHERE T1.transid = T2.transid AND +
       transdate BETWEEN .vdate1 AND .vdate2  +
       GROUP BY transid
 
     LIST VIEW v_trans
     View: v_trans            (transid, amount)
 
     SELECT transid,SUM (extprice) FROM transdetail
     T1,transmaster T2 WHERE T1.transid = T2.transid AND
     transdate BETWEEN '9/1/95' AND '9/30/95' GROUP BY transid
 
     To store the variable name as part of the view definition, put
     parentheses around the variables in the CREATE VIEW command:
 
     SET VAR vdate1 DATE = 9/1/95, vdate2 DATE = 9/30/95 CREATE VIEW+
     v_trans (transid, amount) AS +
       SELECT transid,SUM (extprice) +
       FROM transdetail T1, transmaster T2 +
       WHERE T1.transid = T2.transid AND +
       transdate BETWEEN (.vdate1) AND (.vdate2 ) +
       GROUP BY transid
 
     LIST VIEW v_trans
     View: v_trans            (transid, amount)
 
     SELECT transid,SUM (extprice) FROM transdetail T1,transmaster T2
     WHERE T1.transid = T2.transid AND transdate BETWEEN (.vdate1) AND
     (.vdate2 ) GROUP BY transid
 
     When the variable name is stored in the view definition the view is
     completely dynamic and generates different data for each user based on
     their current values of the variables. Note, however, that the view
     does not use indexes to retrieve the data if the variables are
     enclosed in parentheses. Indexes are used to link the tables, but not
     to qualify the rows using other conditions. Instead of putting the
     WHERE clause in the view definition, another option is to add the
     WHERE clause to the command that uses the view. This way indexes are
     used to qualify rows as well as to link rows.
 
     CREATE VIEW v_trans (transid, amount) AS +
       SELECT transid,SUM (extprice) +
       FROM transdetail T1, transmaster T2 +
       WHERE T1.transid = T2.transid +
       GROUP BY transid
     SET VAR vdate1 DATE = 9/1/95, vdate2 DATE = 9/30/95
     SELECT * FROM v_trans +
       WHERE transdate BETWEEN .vdate1 AND .vdate2
 
     Referencing Columns in Views
     A frequent question about views is "How do you refer to the column
     names in a view? T1.transid or just transid?" Remember a view is a
     stored SELECT command. The stored command, the view, uses the
     correlation names, T1, for example, that are stored with it. Other
     commands that use the view have their own, separate correlation
     names. The correlation names used in the column list and the WHERE
     clause of the view definition are not used in the column list, WHERE
     clause, or ORDER BY clause of the command accessing the view.
 
     For example, look at the following view definition: 
 
     View: empview
     SELECT T1.empid, T1.emplname, T1.empfname, T1.empcity, T1.empstate
     FROM Employee T1
 
     The T1 is a correlation name for the stored SELECT command only. When
     the view is accessed by another SELECT command, that SELECT command
     has its own correlation names.
 
     SELECT EV.empid, EV.emplname, SUM(invoicetotal) +
     FROM empview EV, transmaster TM +
     WHERE TM.empid = EV.empid +
     GROUP BY EV.empid, EV.emplname
 
     In this command, the transmaster table has a correlation of TM, the
     view empview has a correlation name of EV. The columns in the view
     are referenced by the correlation name EV from the executed command,
     not the correlation name T1 that is part of the view, a stored SELECT
     command. The columns could also be referenced by the view name, for
     example, empview.emplname.
 
     Create Tables From Views
     Views are handy because they allow you to manipulate your data, join
     tables, and customize data output without storing additional data in
     the database. Views dynamically generate the data each time you use
     the view so the data is always up to date. However, you can use a view
     to create a permanent table in your database. The PROJECT command
     creates a table with the column definitions and data from the view
     definition. The view must have named columns. If the view has any
     unnamed columns or expressions, R:BASE is unable to create column
     names in the table. The column data types are automatically
     determined: if the column name is already defined, the new table picks
     up that column's data type; if the column in the view is a TEXT
     expression, the data type is always NOTE; other expressions are
     assigned the data type of the expression result. Once the table has
     been created, it contains that particular set of data. The data is
     not updated unless explicitly edited.
 
     For example, the following command creates a table, sales_table,
     using the current data retrieved by the view v_trans. Once the table
     is created the data in the table is static unless edited by the user.
 
     PROJECT sales_table FROM v_trans USING ALL
 
     Views on Views
     You are not limited to creating views on tables, you can also create
     views on views. That means that in a CREATE VIEW command or SELECT
     command a view can be used just like a table. The ability to build a
     view on a view lets you solve even more database problems using views.
     There are many queries that cannot be done with a single command. By
     using views, you can manipulate the data in steps to get the final
     result you want.
 
     For example, you cannot group data by month using a date data type
     column in a SELECT command. You need to have a separate column to
     store the month. However, you can use a view to generate a data set
     that contains just the month instead of the full date value. Then,
     queries that need to be grouped by month are based on the view instead
     of the table. You don't need to store extra data in your database.
 
     CREATE VIEW trans_month +
       (transid, custid, empid, month, +
       netamount, freight, tax, invoicetotal) AS +
       SELECT transid, custid, empid, (IMON(transdate)), +
       netamount, freight, tax, invoicetotal +
       FROM transmaster
 
     The view trans_month contains the integer value for the month
     (January = 1) instead of the full date. You can then easily generate
     sales data grouped by month using the view rather than the actual
     table.
 
     Use Test Data
     Sometimes, a command works great when you test it, then fails when put
     into a production system. The difference is that the production system
     has more data, and happens to contain a subset of data that causes the
     command to fail. Make sure that you have a test data set that contains
     a row of data for each condition that might be met, both true and
     false. Then when you test a view using a SELECT command, you know that
     the command is correct and gives you the expected results in every
     data situation.