=====================================================================
     Using Constraints in 4.5
     =====================================================================
     PRODUCT: R:BASE            VERSION: 4.5
     =====================================================================
     AREA: INTEGRITY            CATEGORY: DB DESIGN, STRUCTURE, INTEGRITY
     =====================================================================
 
     One of the new features in 4.5 is constraint support. Constraints 
     provide automatic data integrity and referential integrity features. 
     In previous versions of R:BASE, data integrity and referential 
     integrity had to be enforced through rules and programming. In 4.5, 
     they are a part of the database structure through constraints and are 
     automatically enforced. The constraints that can be defined are 
     primary key, foreign key, not null and unique.
 
     Primary key/Foreign key
 
     *  primary key
 
     A primary key is the column, or set of columns, that uniquely 
     identifies a row in a table. In other words, it is a set of values 
     that distinguishes one row from another. This could be something like 
     an employee id column in an employee table or it could be a 
     combination of the customer's id and the customer's phone number. 
     Every table will have a column or set of columns that identify a row, 
     but not every table will have a defined primary key. A primary key 
     cannot be defined if any one of the columns included in the desired 
     key already have null or duplicate values. Defining a primary key 
     automatically enforces not null, unique constraints on the column. A 
     primary key definition can be used instead of a rule to prevent 
     duplicates, and will be faster. R:BASE automatically builds an index 
     on the specified column(s) when a primary key is defined.
 
     *  foreign key
     
     Like a primary key, a foreign key is a column or a group of columns. 
     A foreign key matches a defined primary key, i.e. the values in a 
     foreign key reference values in the primary key. A primary key can 
     exist without a foreign key, but a foreign key cannot exist without a 
     primary key. A foreign key is always defined to reference a primary 
     key. A foreign key automatically checks that the values in the foreign 
     key exist in the referenced primary key. A foreign key replaces a 
     verify a value rule. An index is automatically built when a foreign 
     key constraint is defined. 
 
     Primary and foreign keys must match in terms of the specified columns. 
     If you have a multi column primary key, you can not have single column 
     foreign keys reference it. If you have a multi column foreign key, it 
     cannot reference a single column primary key. When a primary key is 
     defined as more than one column, those columns are treated as a whole. 
     Primary and foreign keys must match exactly. Thus if your primary key 
     is defined as full-text, then the corresponding foreign keys referencing 
     it must also be full-text.
 
     Primary and foreign keys automatically preserve referential integrity. 
     You cannot delete a row from a table with a defined primary key if 
     there are referenced foreign keys, thus you can never have detail 
     records without a matching master record. You can delete a row from a 
     table with a foreign key. You cannot add a row to table with a foreign 
     key defined unless the value entered matches a value in the referenced 
     primary key. You cannot update a primary key value if there are 
     references, thus you are ensured that linking columns always match. 
     You can update primary key values, if there are not matching values in 
     the referenced foreign key. 
 
     Not Null
 
     Placing a not null constraint on a column requires that the data in 
     the column must contain a value, it cannot be null. This prevents 
     users from adding a "blank" value to a table. A not null constraint 
     cannot be added if the column already contains null values. The null 
     values must first be edited to actual data values, then the not null 
     constraint can be added. A not null constraint can replace a "Require 
     a value" rule. R:BASE does not build an index for a not null 
     constraint, but since it stores the not null as part of the column 
     definition, it is able to check the constraint faster than it could 
     check the rule.
 
     Unique 
     
     A unique constraint requires that the data values in the column be 
     unique, i.e. the column cannot contain duplicate values. By 
     definition, the column must also be defined as NOT NULL. A unique 
     constraint can replace a "Require a unique value" rule. A unique 
     constraint also automatically builds an index. The unique constraint 
     can only be defined through the R> prompt using either the CREATE 
     TABLE or ALTER TABLE command. For example,
 
     ALTER TABLE tblname ALTER COLUMN colname datatype NOT NULL UNIQUE
 
     Benefits of Constraints
 
     Constraints provide automatic, database wide data integrity and 
     referential integrity. The not null and unique constraints restrict 
     data entry. No matter what command is used to enter data, the 
     constraint verifys that the specified column has a value and the value 
     is unique. The primary, foreign key constraints provide both data 
     integerity and referential integrity. The primary key column is 
     automatically not null and unique. Deletions to a table with a defined 
     primary key are automatically restricted if a referenced foreign key 
     is defined. A value cannot be entered into a table with a foreign key 
     unless that value exists in the referenced primary key table. In 
     previous versions of R:BASE rules could be used to force these 
     constraints.
 
     Using rules to enforce these same data constraints required several 
     different rules. You would need a rule to prevent duplicates (replaced 
     by the primary key or unique constraint), verify a value rules 
     (foreign key), and require a value rules (not null). In addition, you 
     would need to define delete rules to prevent rows being deleted from 
     the primary key table if there were matching rows in the foreign key 
     table. If you wanted to prevent users from changing a primary key 
     value that exists in the foreign key table, you would need to define 
     an additional verify a value rule. Constraints are quicker and easier 
     than rules. Unlike rules, constraints cannot be turned off, they are 
     always checked for. Constraints also provide much faster performance 
     than rules, but can use more disk space since constraints are enforced 
     by using indexes. Many rules, however, also required the rule column 
     to be indexed for performance. It is recommended where possible to use 
     constraints over rules for faster performance and ease of use. Rules 
     are still needed to check other conditions, such as checking for 
     specific values or a range of values.
 
     Defining Constraints
 
     Constraints are defined using the Info Create/modify menu or through 
     the CREATE TABLE or ALTER TABLE commands. Primary key, foreign key and 
     not null constraints can be defined through the menus by just 
     selecting the desired tables and columns from a menu. Unique 
     constraints can only be defined from the R> prompt. Defining a primary 
     key or unique constraint from the R> prompt using CREATE TABLE or 
     ALTER TABLE commands requires the column be explicitly defined as NOT 
     NULL as well as the unique or primary key designation. However, 
     defining a primary key from the menus does not require the explicit 
     NOT NULL, the menus do it for you automatically. For example,
 
     CREATE TABLE tblname (colname datatype NOT NULL PRIMARY KEY, ...)
 
     Before defining primary and foreign key constraints, decide which 
     column or columns and which tables are best suited for the primary 
     key. The column or columns selected should be the ones that uniquely 
     identify the row from other rows in the table, and the table should be 
     the one where that value is first entered into the database and is 
     unique. Linking columns are generally good candidates for primary, 
     foreign key constraints. For example, in the Concomp sample database, 
     the empid column is used to link data in the Employee table with data 
     in the Transmaster table and data in the Salesbonus table. Since a 
     record is first entered into the Employee table, and when data is 
     entered into the Transmaster or Salesbonus tables a matching record 
     must already exist in the Employee table, the empid column in Employee 
     becomes the primary key. The empid columns in Transmaster and 
     Salesbonus become foreign keys referencing the Employee table primary 
     key.
 
     What benefit is gained from designating empid as a primary key in the 
     Employee table and foreign keys in the Transmaster and Salesbonus 
     tables? By this designation you are protecting your data from 
     inadvertent changes. The empid value in Employee cannot be changed 
     when there is a matching row in the Transmaster or Salesbonus table. 
     Rows cannot be deleted from either table. When adding data to 
     Transmaster or Salesbonus you automatically require a matching value 
     in Employee without having to define a rule.
 
     Listing Constraints
 
     LIST CONSTRAINTS from either the menu or the R> prompt shows primary 
     key, foreign key and unique constraints. The constraint ID, the type 
     of constraint, the table name, and table references if the key was a 
     foreign key are displayed. Not null constraints are not displayed.
 
     LIST CONSTRAINTS
     
     Id     Type                          Table Name         References
     ------ ----------------------------- ------------------ ---------------
     #23    UNIQUE                        product
     #26    PRIMARY KEY REFERENCED        employee
     #28    FOREIGN KEY                   transmaster        employee
     #27    FOREIGN KEY                   salesbonus         employee
 
     To see not null constraint information, you use the LIST TABLE command 
     at the R> prompt. That also shows primary and foreign key and unique 
     constraints.
 
     LIST TABLE employee
 
     Table: employee
     Descr: Employee information
     No. Column Name        Attributes
     --- ------------------ -----------------------------------------------
       1 empid              Type   : INTEGER
                            Consrnt: PRIMARY KEY REFERENCED
                            Comment: Employee identification number
 
       2 emptitle           Type   : TEXT 30
                            Comment: Employee job title
 
       3 empfname           Type   : TEXT 10
                            Comment: Employee first name
 
     LIST TABLE salesbonus
     Table: salesbonus
     Descr: Sales bonus information
     No. Column Name        Attributes
     --- ----------- ------------------------------------------------------
       1 empid              Type   : INTEGER
                            Consrnt: FOREIGN KEY REFERENCES employee
                            Comment: Employee identification number
 
       2 transdate          Type   : DATE     NOT NULL
                            Comment: Transaction date
 
       3 netamount          Type   : CURRENCY
                            Comment: Net amount of transaction
 
       4 bonuspct           Type   : REAL
 
     LIST TABLE product
     Table: product
     Descr: Model information, including list price
     No. Column Name        Attributes
     --- ----------- ------------------------------------------------------
       1 model              Type   : TEXT 6 NOT NULL
                            Consrnt: UNIQUE
                            Comment: Product model number
 
       2 prodname           Type   : TEXT 35
                            Comment: Product name
 
 
     Removing Constraints
 
     A primary key constraint that is referenced by a foreign key cannot be 
     removed until the foreign key constraint has first been deleted. If a 
     column was first defined as not null, and then as a primary key, the 
     not null constraint on the column cannot be removed until the primary 
     key constraint has been removed.  Removing a primary key constraint 
     does not remove the NOT NULL part of the constraint.  That must be 
     removed seperately.
     
     Messages
 
     When primary key, foreign key and not null constraints are defined, 
     custom violation messages can be entered. The messages cannot be added 
     or modified after the constraint is defined. The constraint must be 
     deleted and re-defined to add or modify custom messages.