Download Referential Integrity in Oracle Rdb

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

Concurrency control wikipedia , lookup

Database wikipedia , lookup

Entity–attribute–value model wikipedia , lookup

Oracle Database wikipedia , lookup

Microsoft Jet Database Engine wikipedia , lookup

Relational algebra wikipedia , lookup

Clusterpoint wikipedia , lookup

Extensible Storage Engine wikipedia , lookup

Open Database Connectivity wikipedia , lookup

Microsoft SQL Server wikipedia , lookup

Database model wikipedia , lookup

SQL wikipedia , lookup

Object-relational impedance mismatch wikipedia , lookup

PL/SQL wikipedia , lookup

Relational model wikipedia , lookup

Transcript
Referential Integrity in Oracle Rdb
Oracle Rdb has fully supported constraint definition and execution since its first version
which was released in 1984. At that time there was no SQL standard, nor did Rdb use the
SQL nomenclature for this feature. Rdb implemented three types of constraints - valid if,
verb time and commit time. Traces of this terminology exist still in the Rdb product, even
in the SQL syntax.
This technical note provides an overview of the referential integrity features available in
the Oracle Rdb product. It is written from an historical perspective examining changes in
this feature since the first versions of Rdb and relates the Rdb and SQL standard features
and terminology.
ANSI and ISO SQL-92 define constraints in various classes: PRIMARY KEY,
FOREIGN KEY, NOT NULL, UNIQUE and CHECK constraints. CHECK is the most
general and can be used to define similar constraints to the other special cases. However,
the added semantics of PRIMARY KEY, etc. can be used by the underlying engine to
optimize the query. For instance a uniqueness constraint such as UNIQUE need only be
evaluated during INSERT on the table, it need not be evaluated on DELETE from a
referenced table as would be required for a FOREIGN KEY.
When a constraint is defined it is immediately validated against existing inserted data to
ensure that no existing data violates the new referential integrity rules. In the case of
domain constraints, the CHECK constraint will be applied to each table and column
which references the domain and it will be validated against existing data in those tables.
Rdb implements all the constraint types by means of stored BLR queries in the database.
BLR is the internal format for a query and can be displayed by using the
RDMS$DEBUG_FLAGS "M" (or SET FLAGS 'MBLR' in Rdb7 and later versions)
during table creation. Alternatively, RMU/EXTRACT/OPTION=DEBUG can be used to
have the stored BLR for most the constraints dumped during table extraction.
Table 1 Constraint Types
Type
Internal name
Comment
Domain
Constraints
Valid If
Can only reference the domain, and therefore can not contain subqueries
Not Deferrable
Verb Time
Constraint
Arbitrary query complexity e.g. subqueries, external routine calls, etc.
These constraints can not be deferred using the EVALUATING clause of
SET TRANSACTION
Deferrable
Immediate
Verb Time
Constraint
Arbitrary query complexity. e.g. subqueries, external routine calls, etc.
These constraints may be deferred using the EVALUATING clause of
SET TRANSACTION
Deferrable
Commit Time
Constraint
Arbitrary query complexity. e.g. subqueries, external routine calls, etc.
1 Domain Constraints
This type of constraint was originally implemented for the VALID IF clause of the RDO language interface
to Rdb. Oracle CDD/Repository also supports the definition of VALID IF constraints in the CDO interface.
The SQL language interface uses VALID IF to implement domain CHECK constraints. It
should be noted that the BLR generated for this type of constraint by SQL is more
complex, slightly different in semantics than what is generated by the RDO or CDO
interfaces.
Domain constraints in Rdb are always NOT DEFERRABLE. Rdb compiles the constraint
(or validation) into the query itself. This makes these types of constraints the most
efficient. As the definition is based on the domain it is limited in what it can check, but is
excellent for range checks, and NOT NULL constraints.
2 VERB TIME versus COMMIT TIME
This internal notation is used to define the evaluation times of a constraint. Some SQL
statements require multiple verbs to implement. However, in general a VERB can be
considered to be the same as a SQL statement.
As each table is referenced by a query its constraints are compiled and stored in the user
process context. If the query doesn't modify columns referenced by the constraint, or
modifies them to the same values as existed before the evaluation, then the constraint
evaluation is bypassed for that row.
Each constraint is a separate query and they are separately optimized and executed.
Therefore, they can be tuned using query outlines by creating an outline with the same
name as the constraint.
In some cases the query generated for the constraint is reworked by the optimizer to a
form which is more easily optimized. For instance, it might be changed to perform direct
DBKEY lookup rather than perform a table or index scan. Other optimizations are also
performed for FOREIGN KEY, UNIQUE and PRIMARY KEY constraints. If CHECK
constraints conform to some known patterns then these will also be reworked by the
optimizer.
A user can define a table, or column constraint and specify if it as DEFERRABLE or
NOT DEFERRABLE which indicates when the constraint is to be executed.
A NOT DEFERRABLE constraint is executed as part of the SQL statement and is often
executed more efficiently (e.g. NOT NULL). In general NOT DEFERRABLE constraints
should be used when integrity is maintained by a single statement. If multiple statements
are required to maintain integrity, with intermediate results that would violate some
constraints, then DEFERRABLE constraints need to be used.
If you use the SQL dialect 'SQL92' (and I recommend that this be used) then Rdb will
manage some NOT DEFERRABLE constraints differently. This is explained below (see
Section 4).
A DEFERRABLE constraint can be executed immediately after the statement up to
commit time. By default it will execute at commit time.
The user can use the SET ALL CONSTRAINT statement to define the timing
(IMMEDIATE, or DEFERRED) as well as force constraint evaluation when SET
CONSTRAINT is used. If SET ALL CONSTRAINT IMMEDIATE is used then all
subsequent statements will be followed by the evaluation of all active DEFERRABLE
constraints. Once evaluated they will not be re-executed unless reactivated by a query.
The mode in this case is reset by the start of the next transaction. SQL also contains a
SET DEFAULT CONSTRAINT MODE statement so that the evaluating time is
established for the entire session.
In Oracle Rdb8 the constraint evaluation time syntax from SQL-92 was completed to
allow some refinement of the constraint definition. The syntax is actually quite involved
but there are only really three options available:
1. NOT DEFERRABLE INITIALLY IMMEDIATE
This is the same as NOT DEFERRABLE from previous versions.
2. DEFERRABLE INITIALLY DEFERRED
This is the same as DEFERRABLE from previous versions.
3. DEFERRABLE INITIALLY IMMEDIATE
This is a new option for SQL and corresponds to the VERB TIME constraints of
RDO.
The database administrator can also force evaluation of all constraints using the
/CONSTRAINT qualifier with the RMU/VERIFY command. This is a useful tool for
checking the referential integrity of the entire database. Note that domain constraints are
not currently evaluated by RMU/VERIFY.
In Rdb7 an option was added to RMU/VERIFY to verify only constraints which
referenced a particular table, or possibly just a particular constraint. In addition
RMU/VERIFY now attempts to validate as many constraints as possible and report those
failing constraints. In prior versions RMU/VERIFY would abort constraint verification
when the first failed.
Rdb also supports an EVALUATING clause on the SET TRANSACTION statement.
This statement can be used to convert a VERB TIME constraint to a COMMIT TIME
constraint (or vice versa) at the transaction startup. For example,
set transaction read write
evaluating JOBS_CHECK at verb time,
EMPS_CHECK at commit time;
A NOT DEFERRABLE constraint can never have its evaluation time changed. However,
in Rdb8 the DEFERRABLE INITIALLY IMMEDIATE constraint can be affected by the
EVALUATING clause.
3 How it all works?
As each user query, stored procedure or trigger is compiled any constraints which are
affected by INSERT, UPDATE and DELETE statements are loaded. Different statements
will cause different constraint to be loaded. For example, an UPDATE will cause a
UNIQUE constraint to be loaded because it updates a constrained column but a DELETE
does not need to load the constraint because uniqueness is no affected by removing a row.
When the statement is executed all the NOT DEFERRABLE constraints are evaluated
and all DEFERRABLE constraints are placed on a list for later processing.
The constraints on this deferred list will be evaluated at COMMIT time, unless the user
initiates a SET ALL CONSTRAINT IMMEDIATE statement. In the latter case the
constraints are evaluated immediately. They are not re-evaluated unless replaced on the
COMMIT list by another query. For the remainder of the transaction deferred constraints
are executed immediately after a statement executes.
There is a subtle timing difference between these DEFERRED IMMEDIATE constraint
evaluations and NOT DEFERRED constraints. A deferred constraint is evaluated when
the API routine rdb_check_constraints is called (on your behalf by SQL), or when a
COMMIT is executed. A not deferred (or verb time) constraint is evaluated during
execution of the query.
4 Changes for SQL-92 Compliance
By default NOT DEFERRABLE is executed row by row which may produced anomalies
such as shown in the following example:
SQL> create table t (c integer unique not deferrable);
SQL> insert into t value (1);
1 row inserted
SQL> insert into t value (1);
-- expected error
%RDB-E-INTEG_FAIL, violation of constraint T_UNIQUE_C caused
operation to fail
-RDB-F-ON_DB, on database
DISK1:[JONES.DATABASES]MF_PERSONNEL.RDB;1
SQL> insert into t value (2);
1 row inserted
SQL> update t set c = c + 1;
-- (1)
%RDB-E-INTEG_FAIL, violation of constraint T_UNIQUE_C caused
operation to fail
-RDB-F-ON_DB, on database
DISK1:[JONES.DATABASES]MF_PERSONNEL.RDB;1
This update statement ( (1) ) should have succeeded since its compound effect is to
update all the rows and so maintain the uniqueness of the columns. However, the
constraint is evaluated a row at a time and for a short time there exists duplicate values
which causes the failure and abort of the statement.
Rdb was changed in V6.0 to conform to the SQL-92 standard. If any constraint
evaluation fails in a multi-row statement (such as a searched UPDATE) then it is deferred
until the end of the UPDATE statement. This scheme has the advantage of the row at a
time evaluation (the most efficient since the row is already in memory) with a fall back to
a per statement evaluation if failures occur.
This same script when run using dialect 'SQL92' results in expected behavior.
SQL> set dialect 'SQL92';
SQL> attach 'filename MF_PERSONNEL';
SQL> create table t (c integer unique not deferrable);
SQL> insert into t value (1);
1 row inserted
SQL> insert into t value (1);
-- expected error
%RDB-E-INTEG_FAIL, violation of constraint T_UNIQUE_C caused operation
to fail
-RDB-F-ON_DB, on database DISK1:[JONES.DATABASES]MF_PERSONNEL.RDB;1
SQL> insert into t value (2);
1 row inserted
SQL> update t set c = c + 1;
2 rows updated
SQL>
5 Can constraints be disabled?
As stated previously a constraint is an extra query to be performed during database updates. It is often
desirable to eliminate this overhead when the data is loaded in bulk or has already been validated.
Prior to Oracle Rdb7 a constraint could only be disabled by using the ALTER TABLE ...
DROP CONSTRAINT statement. When the constraint is later redefined using ALTER
TABLE ... ADD CONSTRAINT the table must be scanned and the data re-validated.
Adding back the dropped constraint can be a time consuming task.
In Oracle Rdb7, RMU/LOAD supports a /NOCONSTRAINTS qualifier that allows
inserts with constraint evaluation disabled. This functionality is further enhanced in
Oracle Rdb8 which provides syntax in CREATE and ALTER TABLE which specifies
that one or more constraints be disabled.
SQL> alter table EMPLOYEES
cont>
disable all constraints;
SQL> show table (constraint) EMPLOYEES
Table constraints for EMPLOYEES:
EMPLOYEES_PRIMARY_EMPLOYEE_ID
Primary Key constraint
Column constraint for EMPLOYEES.EMPLOYEE_ID
Evaluated on COMMIT
Source:
EMPLOYEES.EMPLOYEE_ID PRIMARY KEY
Constraint is disabled
.
.
.
When the constraint is enabled the table is scanned to ensure database integrity. The
ENABLE NOVALIDATE option allows a knowledgeable database administrator to
avoid the time and I/O resources required to re-validate data when the data is already
valid. In this case the table is not scanned and Rdb assumes table data correctness. You
must be a privilege user to use the NOVALIDATE clause. Use the SHOW TABLE
command to see if the constraint is in a "not validated" state.
SQL> alter table EMPLOYEES
cont>
enable novalidate all constraints;
SQL> show table (constraint) EMPLOYEES
Table constraints for EMPLOYEES:
EMPLOYEES_PRIMARY_EMPLOYEE_ID
Primary Key constraint
Column constraint for EMPLOYEES.EMPLOYEE_ID
Evaluated on COMMIT
Source:
EMPLOYEES.EMPLOYEE_ID PRIMARY KEY
Constraint is not validated
.
.
.
Although constraint are disabled, they can still be explicitly evaluated using the
RMU/VERIFY command. RMU ignores the disabled state when the constraint is
explicitly named with the /CONSTRAINT qualifier. This allows important business rules
to be added to the database and verified periodically. For instance, some complex
business rules are enforced by the user applications and doubly checking them with
constraints might be an unacceptable overhead. Now they can be defined in the database,
kept disabled and verified by the database administrator at convenient times.
Appendix A
Some History of Constraint Evaluation in Rdb
Several interesting sections have been extracted from the Rdb release notes. The product
names have been left as originally publish.
A.1 From the Rdb V2.1/V2.2 Release Notes
A.1.1 Constraint Optimizations
Several types of constraint evaluation operations have been optimized in V2.1:

Existence

Uniqueness

Modification

Database key (dbkey) retrieval and erasing

Multiple evaluations
The following sections describe the nature of these optimizations.
A.1.1.1 Existence Constraint
The existence constraint, which is implemented by using the "REQUIRE <conditional-expr>" option of the
DEFINE CONSTRAINT statement, is not evaluated when you store records in or erase records from
relations named in the constraint. For example:
DEFINE CONSTRAINT EMP_EXISTS
FOR SH IN SALARY_HISTORY
REQUIRE ANY E IN EMPLOYEES
WITH E.EMPLOYEE_ID = SH.EMPLOYEE_ID.
Rdb/VMS need not evaluate this constraint when you store records in EMPLOYEES
relation or erase records from the SALARY_HISTORY relation. If the query includes a
"NOT ANY" clause, Rdb/VMS does not require constraint evaluation when you erase
records from either relation.
A.1.1.2 Uniqueness Constraint
The uniqueness constraint is not evaluated when a record in a relation named in the constraint is erased
from the database. See the following example.
DEFINE CONSTRAINT EMP_UNIQUE
FOR E IN EMPLOYEES
REQUIRE UNIQUE E1 IN EMPLOYEES
WITH E1.EMPLOYEE_ID = E.EMPLOYEE_ID.
This constraint does not have to be evaluated when you erase records from the
EMPLOYEES relation.
A.1.1.3 Modification Operation
If the fields in the relation you modify are not named in the constraint definition, Rdb/VMS need not
evaluate the constraint. For example:
DEFINE CONSTRAINT EMP_ID_RANGE
FOR E IN EMPLOYEES
REQUIRE REQUIRE E.EMPLOYEE_ID > "00000".
If you modify fields other than EMPLOYEE_ID in the EMPLOYEES relation, Rdb/VMS
does not have to evaluate this constraint.
If any field named in the constraint is a COMPUTED BY field, the constraint always is
evaluated whenever you modify any field in the relation.
If the modification is an equivalence statement, the constraint does not have to be
evaluated. For example, Rdb/VMS does not evaluate the constraint when the following
query executes:
FOR E IN EMPLOYEES
MODIFY E USING E.EMPLOYEE_ID = E.EMPLOYEE_ID
END_FOR
A.1.1.4 Database Key Retrieval and Erasing
Consider the following constraint definition:
DEFINE CONSTRAINT EMP_EXIST_SH
FOR E IN EMPLOYEES
REQUIRE ANY SH IN SALARY_HISTORY
WITH SH.EMPLOYEE_ID = E.EMPLOYEE_ID.
Rdb/VMS uses database keys to locate records in the database for retrieval. In this
example, any query executed for the EMPLOYEES relation processes records in that
relation one record at a time. Because Rdb/VMS already has dbkeys for each record it
processes, the constraint evaluation mechanism can use these database keys to retrieve
single records for constraint evaluation. Previous versions of Rdb/VMS might have
processed such a constraint definition for all records in the relation named in the RSE of
the FOR clause in the constraint definition.
The relations in the RSE of the FOR component in the constraint definition never violate
the constraint when you erase records from them. Therefore, the constraint will not be
evaluated.
A.1.1.5 Multiple Evaluations
Multiple evaluations of a constraint definition do not occur for relations mentioned more than once. For
example:
DEFINE CONSTRAINT EMP_UNIQUE
FOR E IN EMPLOYEES
REQUIRE UNIQUE E1 IN EMPLOYEES
WITH E1.EMPLOYEE_ID = E.EMPLOYEE_ID.
Although this constraint definition specifies the EMPLOYEES relation twice, Rdb/VMS
does not need to evaluate this constraint more than once for this relation. In fact, if the
relation is named in the RSE of the constraint definition FOR statement, Rdb/VMS uses
the dbkey retrieval strategy described in the previous section.
A.2 From the Rdb V4.0 Release Notes
A.2.1 Constraint Evaluation
The following improvements have been made to constraint evaluation:

Constraint evaluation on a MODIFY or UPDATE clause
Rdb/VMS evaluates constraints on a MODIFY or UPDATE clause only when the column values
change. Rdb/VMS no longer evaluates constraints if the columns referenced by the constraints
have not actually been modified.

Constraints consume less compilation and execution resources
Constraint compilation for any given update request now takes up to 50% less time, and the
resultant constraint execution structures take up to 50% less virtual memory. In addition, the
number of constraints queued for deferred execution (CHECK ON COMMIT) is frequently less,
by a factor of the number of rows updated per the request.

FOREIGN KEY constraints optimized for verb time evaluation
Updates and deletions to PRIMARY KEY values referenced by FOREIGN KEY constraints no
longer cause a full scan of the PRIMARY KEY table when the FOREIGN KEY constraint is
executed at verb time. Such constraints are optimized to compare the FOREIGN KEY column
values against only the old values of the PRIMARY KEY columns. This optimization is not
available for constraints whose evaluation is deferred until SQL statement end or COMMIT.
A.2.2 Cautions on Using ANY, ALL, or IN Clauses in Constraint
Definitions
For Rdb V3.1, a change was made to correct the results returned by the ANY (SOME) and ALL predicates
to conform to the ANSI/ISO SQL standard. The changes required for ANSI compliance produced a
different type of query for ANY and ALL (and for the IN predicate when a query expression is used) such
that the query can no longer be selectively evaluated when used in a constraint. The workaround for any
performance problems introduced by this change is re-creating the affected constraint with an EXISTS
predicate (or equivalent) applied to a column select expression, as shown in the following example:
CHECK (T1.F1 IN (SELECT T2.F1 FROM T2))
- to CHECK (EXISTS (SELECT * FROM T2 WHERE T2.F1 = T1.F1))
- or CHECK ((SELECT COUNT (*) FROM T2 WHERE T2.F1 = T1.F1) <> 0)
A.3 From the Rdb V6.0 Release Notes
A.3.1 Constraint BLR May Not Reflect Actual Execution Strategy
When :DEC Rdb compiles a primary or foreign key constraint query, the constraint handling code in :DEC
Rdb in most cases reformats the query structure to enable the optimizer to generate the most efficient
strategy for constraint evaluation. The reformatting of a constraint query is internal to :DEC Rdb and
therefore is not visible to the user or to other layered software products, such as :DEC RdbExpert.
As a result of internal reformatting of a constraint query the actual execution strategy
used to evaluate the constraint may be much different from what it would have been if no
internal reformatting was done. The constraint binary language representation (BLR)
simply shows the standard format of a primary or foreign key constraint query. It does
not reflect any internal reformatting performed by :DEC Rdb. Therefore, you cannot
draw conclusions from a constraint BLR about the execution strategy used by :DEC Rdb
to evaluate the constraint.
A.3.2 New RDMS$DEBUG_FLAGS Logical Name Flag Combinations
Show Query Outlines
For :DEC Rdb for OpenVMS VAX V6.0, defining the RDMS$DEBUG_ FLAGS logical name with the
following flag combinations enables display of query outline definitions:

"Ss" flags-display query outline definitions for all nonsystem queries.

"ISs" flags-display query outline definitions for system-created queries such as those generated
when :DEC Rdb compiles constraint and trigger internal queries.

"ISsn" flags-display the names of the constraints or triggers (or both) for which query outlines are
generated.
For example, the following command combines the "I" (Internals) flag with the "Ss"
(Dump query outlines) flags:
$ DEFINE RDMS$DEBUG_FLAGS "ISs"
The following command adds the "n" (Show names) flag to the flags in the preceding
example:
$ DEFINE RDMS$DEBUG_FLAGS "ISsn"
Note that the "s" and "n" flags must be lowercase and must follow immediately after the
uppercase "S" (Strategy) flag.
A.4 From the V6.1 Release Notes
A.4.1 Named Query Outlines May Now Be Used by Triggers and
Constraints
During compilation of a constraint or trigger, Rdb will now search for a query outline with the same name
as the trigger or constraint being compiled. If a match is found, that outline will be used during the query
compilation of the trigger or constraint. If no outline is found matching the name of the object, Rdb will
then try to locate an appropriate outline using the BLR ID of the query. For example:
SQL> create table TAB1 (a1 int constraint TAB1NOTNULL not null,
cont>
a2 char(10),
cont>
a3 char(10) );
SQL> create outline TAB1NOTNULL
cont> id '8755644BCB040948E28A76B6D77CC2D3'
cont> mode 0
cont> as (
cont>
query (
cont>
subquery (
cont>
TAB1 0 access path sequential
cont>
)
cont>
)
cont>
)
cont> compliance optional
;
SQL> create trigger TAB1TRIG before insert on TAB1
cont> (update TAB1 set a3= 'bbbb' where a2 = 'aaaa') for each row;
SQL> create outline TAB1TRIG
cont> id '990F90B45658D27D64233D88D16AD273'
cont> mode 0
cont> as (
cont>
query (
cont>
subquery (
cont>
TAB1 0 access path sequential
cont>
)
cont>
)
cont>
)
cont> compliance optional
;
.
.
.
$ DEFINE RDMS$DEBUG_FLAGS "SnsI"
.
.
.
SQL> insert into tab1 (a1) value (11);
~S: Trigger name TAB1TRIG
~S: Outline TAB1TRIG used
~S: Outline TAB1NOTNULL used
Conjunct
Get
Retrieval sequentially of relation TAB1
.
.
.
1 row inserted
SQL> commit;
~S: Constraint TAB1NOTNULL evaluated
Conjunct
Get
Retrieval sequentially of relation TAB1
A.5 From the Rdb7 Release Notes
A.5.1 SQL92 Intermediate Level UNIQUE Constraint available in Rdb7
Oracle Rdb now provides an SQL92 intermediate level compliant UNIQUE constraint. This type of
constraint excludes columns which are NULL from the UNIQUE comparison. This effectively allows sets
of columns to be UNIQUE or NULL.
This type of constraint will be created by default when the SQL dialect is set to 'SQL89',
'MIA', 'ORACLE LEVEL1' or 'SQL92'. The default dialect is SQLV40. Oracle
recommends that you set the dialect to SQL92 (or one of the listed dialects) before using
CREATE or ALTER TABLE to add UNIQUE constraints to tables.
Note
The new UNIQUE semantics will be used at run-time under any selected dialect. i.e.
the table must be created or altered under the listed dialects to have the new style of
unique enabled.
Improved Performance
The new UNIQUE constraint implementation, in addition to conforming to the Database
Language SQL standard (SQL92 Intermediate Level) also provides improved
performance for single row inserts. This is made possible by eliminating checks for
NULL values from the selection expression and thus simplifying the optimization for
unique checking.
Here is a comparison of the old and new optimizer strategies. In this example a UNIQUE
constraint ("UNIQUE_A") and index on column A is used to check for uniqueness during
an INSERT statement. Note that the optimizer chooses a full range search of the index
(i.e. [0:0]).
~S: Constraint "UNIQUE_A" evaluated
Cross block of 2 entries
Cross block entry 1
Conjunct
Firstn Get
Retrieval by DBK of relation
T_UNIQUE
Cross block entry 2
Conjunct
Aggregate-F2
Conjunct
Index only retrieval of relation T_UNIQUE
Index name T_UNIQUE_INDEX_A [0:0]
With the simplified UNIQUE constraint ("UNIQUE_B") the optimizer can use a direct
lookup of the index (i.e. [1:1]) which reduces the I/O to the index to perform the
constraint evaluation.
~S: Constraint "UNIQUE_B" evaluated
Cross block of 2 entries
Cross block entry 1
Conjunct
Firstn Get
Retrieval by DBK of relation
T_UNIQUE
Cross block entry 2
Conjunct
Aggregate-F2
Index only retrieval of relation
T_UNIQUE
Index name T_UNIQUE_INDEX_B [1:1]
Upward Compatibility
The UNIQUE constraint in prior versions restricted columns to a single NULL value. If
you wish to retain this behavior then use the SET DIALECT 'SQLV40' statement before
creating new tables or altering existing tables to add UNIQUE constraints.
UNIQUE constraints created in previous versions of Oracle Rdb will still perform as in
previous versions. Interfaces such as RDO, or the CDD/Repository will continue to
define the older style UNIQUE constraint. It is expected that future versions of the Oracle
CDD/Repository will implement the new UNIQUE constraint. Database EXPORT and
IMPORT will retain the UNIQUE constraint characteristics as defined by the database
administrator, regardless of the defined dialect setting.
Note
RMU Extract Item=Table will not distinguish between the old and new UNIQUE
constraints in this release of Rdb. The generated SQL script must be modified to
establish the appropriate dialect before using it to create a database.
As this new style of UNIQUE constraint is a relaxation of the UNIQUE rules, it is
possible to drop the old style UNIQUE constraint and redefine the constraint under the
SQL92 dialect.
Note that this meaning of UNIQUE (i.e. excluding NULL from the uniqueness test) does
not apply to the UNIQUE index which still does not allow duplicate entries for NULL. If
a UNIQUE index is currently defined which assists the UNIQUE constraint optimization,
the database administrator may wish to drop the index and make it a non-UNIQUE index
so that multiple NULLs can be stored. The UNIQUE constraint will still enforce the
uniqueness of the data.
You can use the SQL SHOW TABLE command to determine which type of UNIQUE
constraint is in use. For example, the first example is a UNIQUE constraint created when
the default dialect was used (SQLV40). A new description follows the "Unique
constraint" text, explaining the interpretation of null values.
SQL> SHOW TABLE (CONSTRAINT) T_UNIQUE
Information for table T_UNIQUE
Table constraints for T_UNIQUE:
T_UNIQUE_UNIQUE_B_A
Unique constraint
Null values are considered the same
Table constraint for T_UNIQUE
Evaluated on UPDATE, NOT DEFERRABLE
Source:
UNIQUE (b,a)
.
.
.
This second example is a UNIQUE constraint created when the dialect was set to
'SQL92', and the description here indicates that all null values are considered distinct.
SQL> SHOW TABLE (CONSTRAINT) T_UNIQUE2
Information for table T_UNIQUE2
Table constraints for T_UNIQUE2:
T_UNIQUE2_UNIQUE_B_A
Unique constraint
Null values are considered distinct
Table constraint for T_UNIQUE2
Evaluated on UPDATE, NOT DEFERRABLE
Source:
UNIQUE (b,a)
.
.
.
Additional Constraint Improvements
As a side effect of this change, Oracle Rdb also recognizes a larger class of CHECK
constraints as being uniqueness checks. The main benefit is that these constraints are no
longer executed when a DELETE is executed for the table, because DELETE does not
affect the uniqueness of the remaining rows.
Such an example would be this CHECK constraint:
SQL> create table T_USER_UNIQUE_NEW (
cont>
a integer,
cont>
b integer,
cont>
constraint unique_ab_new
cont>
check ((select count(*)
cont>
from T_USER_UNIQUE_NEW t2
cont>
where t2.a = T_USER_UNIQUE_NEW.a and
cont>
t2.b = T_USER_UNIQUE_NEW.b) <= 1)
cont>
not deferrable
cont>
);
In previous versions of Rdb only equality with 1 was recognized as a uniqueness
constraint. In this example a comparison of LESS THAN or EQUAL to one also qualifies
as a uniqueness constraint.
A.5.2 Domain Check Constraints and NULL
The VALID IF clause (available in RDO and CDD/Repository) is also used to implement the SQL domain
CHECK constraint. However, it implements different semantics from a SQL column CHECK clause as
defined by the SQL92 standard. The difference is in the handling of the check expression when it is
evaluated as NULL.
For instance, a column CHECK constraint (col > 0) fails if the non-null value of "col"
exceeds 0. However, a null value does not cause a column constraint failure. On the other
hand, a VALID IF (used to implement a domain CHECK constraint) would cause a
failure when the expression evaluated to NULL.
Oracle Rdb V7.0 now detects that the VALID IF is being used as a domain CHECK
constraint and applies the same semantics for NULL as with column CHECK constraints.
To inherit this new behavior the domain CHECK constraint must be redefined for all
domains in the database. The following example shows the alter clause which redefines
the CHECK constraint
SQL> alter domain SALARY check (value > 0.00) not deferrable;
This ALTER DOMAIN statement will cause the domain to be propagated to all
referencing columns.
This problem has been corrected in Oracle Rdb Version 7.0 for all new or altered check
constraint. CHECK constraints created by previous versions of Rdb will continue to
exhibit incorrect (or at least inconsistent) handling of NULL when compared to column
CHECK constraints.
Note
The behavior of CDD or RDO defined constraints is unchanged. The constraint
must be defined through the SQL interface to inherit the semantics described by
this release note.