PK
|%Aoa, mimetypeapplication/epub+zipPK |%A iTunesMetadata.plist\
If the definition of object A references object B, then A depends on B. This chapter explains dependencies among schema objects, and how Oracle Database automatically tracks and manages these dependencies. Because of this automatic dependency management, A never uses an obsolete version of B, and you almost never have to explicitly recompile A after you change B.
Topics:
Some types of schema objects can reference other objects in their definitions. For example, a view is defined by a query that references tables or other views, and the body of a subprogram can include SQL statements that reference other objects. If the definition of object A references object B, then A is a dependent object (of B) and B is a referenced object (of A).
Example 18-1 shows how to display the dependent and referenced object types in your database (if you are logged in as DBA).
Example 18-1 Displaying Dependent and Referenced Object Types
Display dependent object types:
SELECT DISTINCT TYPE FROM DBA_DEPENDENCIES ORDER BY TYPE;
Result:
TYPE ------------------ DIMENSION EVALUATION CONTXT FUNCTION INDEX INDEXTYPE JAVA CLASS JAVA DATA MATERIALIZED VIEW OPERATOR PACKAGE PACKAGE BODY TYPE ------------------ PROCEDURE RULE RULE SET SYNONYM TABLE TRIGGER TYPE TYPE BODY UNDEFINED VIEW XML SCHEMA 22 rows selected.
Display referenced object types:
SELECT DISTINCT REFERENCED_TYPE FROM DBA_DEPENDENCIES ORDER BY REFERENCED_TYPE;
Result:
REFERENCED_TYPE ------------------ EVALUATION CONTXT FUNCTION INDEX INDEXTYPE JAVA CLASS LIBRARY NON-EXISTENT OPERATOR PACKAGE PROCEDURE SEQUENCE REFERENCED_TYPE ------------------ SYNONYM TABLE TYPE VIEW XML SCHEMA 16 rows selected.
If you alter the definition of a referenced object, dependent objects might not continue to function without error, depending on the type of alteration. For example, if you drop a table, no view based on the dropped table is usable.
As an example of a schema object change that invalidates some dependents but not others, consider the two views in Example 18-2, which are based on the HR
.EMPLOYEES
table.
Example 18-2 creates two views from the EMPLOYEES
table: SIXFIGURES
, which selects all columns in the table, and COMMISSIONED
, which does not include the EMAIL
column. As the example shows, changing the EMAIL
column invalidates SIXFIGURES
, but not COMMISSIONED
.
Example 18-2 Schema Object Change that Invalidates Some Dependents
CREATE OR REPLACE VIEW sixfigures AS SELECT * FROM employees WHERE salary >= 100000; CREATE OR REPLACE VIEW commissioned AS SELECT first_name, last_name, commission_pct FROM employees WHERE commission_pct > 0.00;
SQL*Plus formatting command:
COLUMN object_name FORMAT A16
Query:
SELECT object_name, status FROM user_objects WHERE object_type = 'VIEW' ORDER BY object_name;
Result:
OBJECT_NAME STATUS ---------------- ------- COMMISSIONED VALID SIXFIGURES VALID
Lengthen EMAIL
column of EMPLOYEES
table:
ALTER TABLE employees MODIFY email VARCHAR2(100);
Query:
SELECT object_name, status FROM user_objects WHERE object_type = 'VIEW' ORDER BY object_name;
Result:
OBJECT_NAME STATUS ---------------- ------- COMMISSIONED INVALID SIXFIGURES VALID
A view depends on every object referenced in its query. The view in Example 18-3, depends on the tables employees
and departments
.
Example 18-3 View that Depends on Multiple Objects
CREATE OR REPLACE VIEW v AS SELECT last_name, first_name, department_name FROM employees e, departments d WHERE e.department_id = d.department_id ORDER BY last_name;
Notes:
|
The static data dictionary views USER_DEPENDENCIES
, ALL_DEPENDENCIES
, and DBA_DEPENDENCIES
describe dependencies between database objects.
The utldtree.sql
SQL script creates the view DEPTREE
, which contains information on the object dependency tree, and the view IDEPTREE
, a presorted, pretty-print version of DEPTREE
.
See Also: Oracle Database Reference for more information about theDEPTREE , IDEPTREE , and utldtree.sql script |
Every database object has a status value described in Table 18-1.
Table 18-1 Database Object Status
Status | Meaning |
---|---|
Valid |
The object was successfully compiled, using the current definition in the data dictionary. |
Compiled with errors |
The most recent attempt to compile the object produced errors. |
Invalid |
The object is marked invalid because an object that it references has changed. (Only a dependent object can be invalid.) |
Unauthorized |
An access privilege on a referenced object was revoked. (Only a dependent object can be unauthorized.) |
Note: The static data dictionary viewsUSER_OBJECTS , ALL_OBJECTS , and DBA_OBJECTS do not distinguish between "Compiled with errors," "Invalid," and "Unauthorized"—they describe all of these as INVALID . |
If object A depends on object B, which depends on object C, then A is a direct dependent of B, B is a direct dependent of C, and A is an indirect dependent of C.
Direct dependents are invalidated only by changes to the referenced object that affect them (changes to the signature of the referenced object).
Indirect dependents can be invalidated by changes to the reference object that do not affect them. If a change to C invalidates B, it invalidates A (and all other direct and indirect dependents of B). This is called cascading invalidation.
With coarse-grained invalidation, a data definition language (DDL) statement that changes a referenced object invalidates all of its dependents.
With fine-grained invalidation, a DDL statement that changes a referenced object invalidates only dependents for which either of these statements is true:
The dependent relies on the attribute of the referenced object that the DDL statement changed.
The compiled metadata of the dependent is no longer correct for the changed referenced object.
For example, if view v
selects columns c1
and c2
from table t
, a DDL statement that changes only column c3
of t
does not invalidate v
.
The DDL statement CREATE
OR
REPLACE
object
has no effect under these conditions:
object
is a PL/SQL object, the new PL/SQL source text is identical to the existing PL/SQL source text, and the PL/SQL compilation parameter settings stored with object
are identical to those in the session environment.
For information about PL/SQL compilation parameter settings, see Oracle Database PL/SQL Language Reference.
object
is a synonym and the statement does not change the target object.
The operations in the left column of Table 18-2 cause fine-grained invalidation, except in the cases in the right column. The cases in the right column, and all operations not listed in Table 18-2, cause coarse-grained invalidation.
Table 18-2 Operations that Cause Fine-Grained Invalidation
Operation | Exceptions |
---|---|
|
|
|
|
Online Table Redefinition ( |
Column lists of new and old definitions differ, and at least one of these is true:
|
|
|
|
|
|
Call signature changes. Call signature is the parameter list (order, names, and types of parameters), return type, purityFoot 1 , determinism, parallelism, pipelining, and (if the procedure or function is implemented in C or Java) implementation properties. |
|
|
Footnote 1 Purity refers to a set of rules for preventing side effects (such as unexpected data changes) when invoking PL/SQL functions within SQL queries. Package purity refers to the purity of the code in the package initialization block.
Footnote 2 The entry-point number of a procedure or function is determined by its location in the PL/SQL package code. A procedure or function added to the end of a PL/SQL package is given a new entry-point number.
Note: A dependent object that is invalidated by an operation in Table 18-2 appears in the static data dictionary views*_OBJECTS and *_OBJECTS_AE only after an attempt to reference it (either during compilation or execution) or after invoking one of these subprograms:
|
Topics:
Each session that references a package construct has its own instantiation of that package, including a persistent state of any public and private variables, cursors, and constants. All of a session's package instantiations, including state, can be lost if any of the session's instantiated packages are subsequently invalidated and revalidated.
See Also:
|
When a data manipulation language (DML) object or system privilege is granted to, or revoked from, a user or PUBLIC
, Oracle Database invalidates all the owner's dependent objects, to verify that an owner of a dependent object continues to have the necessary privileges for all referenced objects.
To reduce invalidation of dependent objects, follow these guidelines:
When adding items to a package, add them to the end of the package. This preserves the entry point numbers of existing top-level package items, preventing their invalidation.
For example, consider this package:
CREATE OR REPLACE PACKAGE pkg1 IS FUNCTION get_var RETURN VARCHAR2; END; /
Adding an item to the end of pkg1
, as follows, does not invalidate dependents that reference the get_var
function:
CREATE OR REPLACE PACKAGE pkg1 IS
FUNCTION get_var RETURN VARCHAR2;
PROCEDURE set_var (v VARCHAR2);
END;
/
Inserting an item between the get_var
function and the set_var
procedure, as follows, invalidates dependents that reference the set_var
function:
CREATE OR REPLACE PACKAGE pkg1 IS
FUNCTION get_var RETURN VARCHAR2;
PROCEDURE assert_var (v VARCHAR2);
PROCEDURE set_var (v VARCHAR2);
END;
/
Reference tables indirectly, using views, enabling you to:
Add columns to the table without invalidating dependent views or dependent PL/SQL objects
Modify or delete columns not referenced by the view without invalidating dependent objects
The statement CREATE
OR
REPLACE
VIEW
does not invalidate an existing view or its dependents if the new ROWTYPE
matches the old ROWTYPE
.
An object that is not valid when it is referenced must be validated before it can be used. Validation occurs automatically when an object is referenced; it does not require explicit user action.
If an object is not valid, its status is either compiled with errors, unauthorized, or invalid. For definitions of these terms, see Table 18-1.
Topics:
Revalidation of Objects that Compiled with Errors
The compiler cannot automatically revalidate an object that compiled with errors. The compiler recompiles the object, and if it recompiles without errors, it is revalidated; otherwise, it remains invalid.
Revalidation of Unauthorized Objects
The compiler checks whether the unauthorized object has access privileges to all of its referenced objects. If so, the compiler revalidates the unauthorized object without recompiling it. If not, the compiler issues appropriate error messages.
Revalidation of Invalid SQL Objects
The SQL compiler recompiles the invalid object. If the object recompiles without errors, it is revalidated; otherwise, it remains invalid.
Revalidation of Invalid PL/SQL Objects
For an invalid PL/SQL program unit (procedure, function, or package), the PL/SQL compiler checks whether any referenced object changed in a way that affects the invalid object. If so, the compiler recompiles the invalid object. If the object recompiles without errors, it is revalidated; otherwise, it remains invalid. If not, the compiler revalidates the invalid object without recompiling it.
Object names referenced in SQL statements have one or more pieces. Pieces are separated by periods—for example, hr
.employees
.department_id
has three pieces.
Oracle Database uses this procedure to try to resolve an object name:
Try to qualify the first piece of the object name.
If the object name has only one piece, then that piece is the first piece. Otherwise, the first piece is the piece to the left of the leftmost period; for example, in hr
.employees
.department_id
, the first piece is hr
.
The procedure for trying to qualify the first piece is:
If the object name is a table name that appears in the FROM
clause of a SELECT
statement, and the object name has multiple pieces, go to step d. Otherwise, go to step b.
Search the current schema for an object whose name matches the first piece.
Search for a public synonym that matches the first piece.
Search for a schema whose name matches the first piece.
If found, and if the object name has a second piece, go to step e. Otherwise, return an error—the object name cannot be qualified.
Search the schema found at step d for a SQL function whose name matches the second piece of the object name.
If found, the schema redefined that SQL function. The object name resolves to the original SQL function, not to the schema-defined function of the same name. Go to step 2.
If not found, return an error—the object name cannot be qualified.
A schema object has been qualified. Any remaining pieces of the object name must match a valid part of this schema object.
For example, if the object name is hr
.employees
.department_id
, hr
is qualified as a schema. If employees
is qualified as a table, department_id
must correspond to a column of that table. If employees
is qualified as a package, department_id
must correspond to a public constant, variable, procedure, or function of that package.
Because of how Oracle Database resolves references, an object can depend on the nonexistence of other objects. This situation occurs when the dependent object uses a reference that would be interpreted differently if another object were present.
See Also:
|
Local dependency management occurs when Oracle Database manages dependencies among the objects in a single database. For example, a statement in a procedure can reference a table in the same database.
Remote dependency management occurs when Oracle Database manages dependencies in distributed environments across a network. For example, an Oracle Forms trigger can depend on a schema object in the database. In a distributed database, a local view can reference a remote table.
Oracle Database also manages distributed database dependencies. For example, an Oracle Forms application might contain a trigger that references a table. The database system must account for dependencies among such objects. Oracle Database uses different mechanisms to manage remote dependencies, depending on the objects involved.
Topics:
Dependencies among stored procedures (including functions, packages, and triggers) in a distributed database system are managed using either time-stamp checking or signature checking (see "Time-Stamp Dependency Mode" and "RPC-Signature Dependency Mode").
The dynamic initialization parameter REMOTE_DEPENDENCIES_MODE
determines whether time stamps or signatures govern remote dependencies.
Oracle Database does not manage dependencies among remote schema objects other than local-procedure-to-remote-procedure dependencies.
For example, assume that a local view is created and defined by a query that references a remote table. Also assume that a local procedure includes a SQL statement that references the same remote table. Later, the definition of the table is altered.
Therefore, the local view and procedure are never invalidated, even if the view or procedure is used after the table is altered, and even if the view or procedure now returns errors when used. In this case, the view or procedure must be altered manually so that errors are not returned. In such cases, lack of dependency management is preferable to unnecessary recompilations of dependent objects.
Code in database applications can reference objects in the connected database. For example, Oracle Call Interface (OCI) and precompiler applications can submit anonymous PL/SQL blocks. Triggers in Oracle Forms applications can reference a schema object.
Such applications are dependent on the schema objects they reference. Dependency management techniques vary, depending on the development environment. Oracle Database does not automatically track application dependencies.
See Also: Manuals for your application development tools and your operating system for more information about managing the remote dependencies within database applications |
Remote procedure call (RPC) dependency management occurs when a local stored procedure calls a remote procedure in a distributed database system. The dynamic initialization parameter REMOTE_DEPENDENCIES_MODE
controls the dependency mode. The choice is either time-stamp dependency mode or RPC-signature dependency mode.
Topics:
Whenever a procedure is compiled, its time stamp is recorded in the data dictionary. The time stamp shows when the procedure was created, altered, or replaced.
A compiled procedure contains information about each remote procedure that it calls, including the schema, package name, procedure name, and time stamp of the remote procedure.
In time-stamp dependency mode, when a local stored procedure calls a remote procedure, Oracle Database compares the time stamp that the local procedure has for the remote procedure to the current time stamp of the remote procedure. If the two timestamps match, both the local and remote procedures run. Neither is recompiled.
If the two timestamps do not match, the local procedure is invalidated and an error is returned to the calling environment. All other local procedures that depend on the remote procedure with the new time stamp are also invalidated.
Time stamp comparison occurs when a statement in the body of the local procedure calls the remote procedure. Therefore, statements in the local procedure that precede the invalid call might run successfully. Statements after the invalid call do not run. The local procedure must be recompiled.
If DML statements precede the invalid call, they roll back only if they and the invalid call are in the same PL/SQL block. For example, the UPDATE
statement rolls back in this code:
BEGIN
UPDATE table SET ... invalid_proc; COMMIT;
END;
But the UPDATE
statement does not roll back in this code:
UPDATE table SET ... EXECUTE invalid_proc; COMMIT;
The disadvantages of time-stamp dependency mode are:
Dependent objects across the network are often recompiled unnecessarily, degrading performance.
If the client-side application uses PL/SQL, this mode can cause situations that prevent the application from running on the client side.
An example of such an application is Oracle Forms. During installation, you must recompile the client-side PL/SQL procedures that Oracle Forms uses at the client site. Also, if a client-side procedure depends on a server procedure, and if the server procedure changes or is automatically recompiled, you must recompile the client-side PL/SQL procedure. However, no PL/SQL compiler is available on the client. Therefore, the developer of the client application must distribute new versions of the application to all customers.
Oracle Database provides RPC signatures to handle remote dependencies. RPC signatures do not affect local dependencies, because recompilation is always possible in the local environment.
An RPC signature is associated with each compiled stored program unit. It identifies the unit by these characteristics:
Name
Number of parameters
Data type class of each parameter
Mode of each parameter
Data type class of return value (for a function)
An RPC signature changes only when at least one of the preceding characteristics changes.
A compiled program unit contains the RPC signature of each remote procedure that it calls (and the schema, package name, procedure name, and time stamp of the remote procedure).
In RPC-signature dependency mode, when a local program unit calls a subprogram in a remote program unit, the database ignores time-stamp mismatches and compares the RPC signature that the local unit has for the remote subprogram to the current RPC signature of the remote subprogram. If the RPC signatures match, the call succeeds; otherwise, the database returns an error to the local unit, and the local unit is invalidated.
For example, suppose that this procedure, get_emp_name
, is stored on a server in Boston (BOSTON_SERVER
):
CREATE OR REPLACE PROCEDURE get_emp_name ( emp_number IN NUMBER, hiredate OUT VARCHAR2, emp_name OUT VARCHAR2) AS BEGIN SELECT last_name, TO_CHAR(hire_date, 'DD-MON-YY') INTO emp_name, hiredate FROM employees WHERE employee_id = emp_number; END; /
When get_emp_name
is compiled on BOSTON_SERVER
, Oracle Database records both its RPC signature and its time stamp.
Suppose that this PL/SQL procedure, print_name
, which calls get_emp_name
, is on a server in California:
CREATE OR REPLACE PROCEDURE print_ename (emp_number IN NUMBER) AS
hiredate VARCHAR2(12);
ename VARCHAR2(10);
BEGIN
get_emp_name@BOSTON_SERVER(emp_number, hiredate, ename);
dbms_output.put_line(ename);
dbms_output.put_line(hiredate);
END;
/
When print_name
is compiled on the California server, the database connects to the Boston server, sends the RPC signature of get_emp_name
to the California server, and records the RPC signature of get_emp_name
in the compiled state of print_ename
.
At run time, when print_name
calls get_emp_name
, the database sends the RPC signature of get_emp_name
that was recorded in the compiled state of print_ename
to the Boston server. If the recorded RPC signature matches the current RPC signature of get_emp_name
on the Boston server, the call succeeds; otherwise, the database returns an error to print_name
, which is invalidated.
Topics:
Changing the name or default value of a subprogram parameter does not change the RPC signature of the subprogram. For example, procedure P1
has the same RPC signature in these two examples:
PROCEDURE P1 (Param1 IN NUMBER := 100); PROCEDURE P1 (Param2 IN NUMBER := 200);
However, if your application requires that callers get the new default value, you must recompile the called procedure.
Because the subprogram parameter mode IN
is the default, you can specify it either implicitly or explicitly. Changing its specification from implicit to explicit, or the reverse, does not change the RPC signature of the subprogram. For example, procedure P1
has the same RPC signature in these two examples:
PROCEDURE P1 (Param1 NUMBER); -- implicit specification
PROCEDURE P1 (Param1 IN NUMBER); -- explicit specification
Changing the body of a subprogram does not change the RPC signature of the subprogram.
Example 18-4 changes only the body of the procedure get_hire_date
; therefore, it does not change the RPC signature of get_hire_date
.
Example 18-4 Changing Body of Procedure get_hire_date
CREATE OR REPLACE PROCEDURE get_hire_date ( emp_number IN NUMBER, hiredate OUT VARCHAR2, emp_name OUT VARCHAR2) AS BEGIN SELECT last_name, TO_CHAR(hire_date, 'DD-MON-YY') INTO emp_name, hiredate FROM employees WHERE employee_id = emp_number; END; / CREATE OR REPLACE PROCEDURE get_hire_date ( emp_number IN NUMBER, hiredate OUT VARCHAR2, emp_name OUT VARCHAR2) AS BEGIN -- Change date format model SELECT last_name, TO_CHAR(hire_date, 'DD/MON/YYYY') INTO emp_name, hiredate FROM employees WHERE employee_id = emp_number; END; /
Changing the data type of a parameter to another data type in the same class does not change the RPC signature, but changing the data type to a data type in another class does.
Table 18-3 lists the data type classes and the data types that comprise them. Data types not listed in Table 18-3, such as NCHAR
, do not belong to a data type class. Changing their type always changes the RPC signature.
Table 18-3 Data Type Classes
Data Type Class | Data Types in Class |
---|---|
CHAR CHARACTER | |
VARCHAR VARCHAR2 STRING LONG ROWID | |
RAW LONG RAW | |
BINARY_INTEGER PLS_INTEGER SIMPLE_INTEGER BOOLEAN NATURAL NATURALN POSITIVE POSITIVEN | |
NUMBER INT INTEGER SMALLINT DEC DECIMAL REAL FLOAT NUMERIC DOUBLE PRECISION | |
DATE TIMESTAMP TIMESTAMP WITH TIME ZONE TIMESTAMP WITH LOCAL TIME ZONE INTERVAL YEAR TO MONTH INTERVAL DAY TO SECOND |
Example 18-5 changes the data type of the parameter hiredate
from VARCHAR2
to DATE
. VARCHAR2
and DATE
are not in the same data type class, so the RPC signature of the procedure get_hire_date
changes.
Example 18-5 Changing Data Type Class of get_hire_date Parameter
CREATE OR REPLACE PROCEDURE get_hire_date (
emp_number IN NUMBER,
hiredate OUT DATE,
emp_name OUT VARCHAR2) AS
BEGIN
SELECT last_name, TO_CHAR(hire_date, 'DD/MON/YYYY')
INTO emp_name, hiredate
FROM employees
WHERE employee_id = emp_number;
END;
/
Changing the name of a package type, or the names of its internal components, does not change the RPC signature of the package.
Example 18-6 defines a record type, emp_data_type
, inside the package emp_package
. Next, it changes the names of the record fields, but not their types. Finally, it changes the name of the type, but not its characteristics. The RPC signature of the package does not change.
Example 18-6 Changing Names of Fields in Package Record Type
CREATE OR REPLACE PACKAGE emp_package AS TYPE emp_data_type IS RECORD ( emp_number NUMBER, hiredate VARCHAR2(12), emp_name VARCHAR2(10) ); PROCEDURE get_emp_data ( emp_data IN OUT emp_data_type ); END; / CREATE OR REPLACE PACKAGE emp_package AS TYPE emp_data_type IS RECORD ( emp_num NUMBER, hire_dat VARCHAR2(12), empname VARCHAR2(10) ); PROCEDURE get_emp_data ( emp_data IN OUT emp_data_type ); END; / CREATE OR REPLACE PACKAGE emp_package AS TYPE emp_data_record_type IS RECORD ( emp_num NUMBER, hire_dat VARCHAR2(12), empname VARCHAR2(10) ); PROCEDURE get_emp_data ( emp_data IN OUT emp_data_record_type ); END; /
The dynamic initialization parameter REMOTE_DEPENDENCIES_MODE
controls the dependency mode. If the initialization parameter file contains this specification, then only time stamps are used to resolve dependencies (if this is not explicitly overridden dynamically):
REMOTE_DEPENDENCIES_MODE = TIMESTAMP
If the initialization parameter file contains this parameter specification, then RPC signatures are used to resolve dependencies (if this not explicitly overridden dynamically):
REMOTE_DEPENDENCIES_MODE = SIGNATURE
You can alter the mode dynamically by using the DDL statements. For example, this example alters the dependency mode for the current session:
ALTER SESSION SET REMOTE_DEPENDENCIES_MODE = {SIGNATURE | TIMESTAMP}
This example alters the dependency mode systemwide after startup:
ALTER SYSTEM SET REMOTE_DEPENDENCIES_MODE = {SIGNATURE | TIMESTAMP}
If the REMOTE_DEPENDENCIES_MODE
parameter is not specified, either in the init.ora
parameter file or using the ALTER
SESSION
or ALTER
SYSTEM
statements, TIMESTAMP
is the default value. Therefore, unless you explicitly use the REMOTE_DEPENDENCIES_MODE
parameter, or the appropriate DDL statement, your server is operating using the time-stamp dependency mode.
When you use REMOTE_DEPENDENCIES_MODE
=SIGNATURE
:
If you change the initial value of a parameter of a remote procedure, then the local procedure calling the remote procedure is not invalidated. If the call to the remote procedure does not supply the parameter, then the initial value is used. In this case, because invalidation and recompilation does not automatically occur, the old initial value is used. To see the new initial values, recompile the calling procedure manually.
If you add an overloaded procedure in a package (a procedure with the same name as an existing one), then local procedures that call the remote procedure are not invalidated. If it turns out that this overloading results in a rebinding of existing calls from the local procedure under the time-stamp mode, then this rebinding does not happen under the RPC signature mode, because the local procedure does not get invalidated. You must recompile the local procedure manually to achieve the rebinding.
If the types of parameters of an existing package procedure are changed so that the new types have the same shape as the old ones, then the local calling procedure is not invalidated or recompiled automatically. You must recompile the calling procedure manually to get the semantics of the new type.
Topics:
When REMOTE_DEPENDENCIES_MODE = TIMESTAMP
(the default value), dependencies among program units are handled by comparing time stamps at run time. If the time stamp of a called remote procedure does not match the time stamp of the called procedure, then the calling (dependent) unit is invalidated and must be recompiled. In this case, if there is no local PL/SQL compiler, then the calling application cannot proceed.
In the time-stamp dependency mode, RPC signatures are not compared. If there is a local PL/SQL compiler, then recompilation happens automatically when the calling procedure is run.
When REMOTE_DEPENDENCIES_MODE = SIGNATURE
, the recorded time stamp in the calling unit is first compared to the current time stamp in the called remote unit. If they match, then the call proceeds. If the time stamps do not match, then the RPC signature of the called remote subprogram, as recorded in the calling subprogram, is compared with the current RPC signature of the called subprogram. If they do not match (using the criteria described in the section "Changing Data Type Classes of Parameters"), then an error is returned to the calling session.
Follow these guidelines for setting the REMOTE_DEPENDENCIES_MODE
parameter:
Server-side PL/SQL users can set the parameter to TIMESTAMP
(or let it default to that) to get the time-stamp dependency mode.
Server-side PL/SQL users can use RPC-signature dependency mode if they have a distributed system and they want to avoid possible unnecessary recompilations.
Client-side PL/SQL users must set the parameter to SIGNATURE
. This allows:
Installation of applications at client sites without recompiling procedures.
Ability to upgrade the server, without encountering time stamp mismatches.
When using RPC signature mode on the server side, add procedures to the end of the procedure (or function) declarations in a package specification. Adding a procedure in the middle of the list of declarations can cause unnecessary invalidation and recompilation of dependent procedures.
In addition to managing dependencies among schema objects, Oracle Database also manages dependencies of each shared SQL area in the shared pool. If a table, view, synonym, or sequence is created, altered, or dropped, or a procedure or package specification is recompiled, all dependent shared SQL areas are invalidated. At a subsequent execution of the cursor that corresponds to an invalidated shared SQL area, Oracle Database reparses the SQL statement to regenerate the shared SQL area.
This topic briefly describes the new Oracle Database features that this book documents and provides links to more information.
Topics:
Edition Attribute of Database Service
Before Release 11.2.0.2, you could not specify your initial session edition when using a database service to connect to Oracle Database. If you wanted to use Edition-Based Redefinition for hot rollover, where some database clients use the pre-upgrade edition while others use the post-upgrade edition, then you had to change the client code.
As of Release 11.2.0.2, you can specify the initial session edition as an attribute of a database service, which makes it easier to ensure that each session uses the desired edition during hot rollover. For more information, see "Your Initial Session Edition".
As of Release 11.2.0.2, each *_SERVICES
static data dictionary view has an EDITION
column that shows the default initial session edition. For more information, see "Displaying Information About Editions, Editioning Views, and Crossedition Triggers".
The Oracle Database features for Oracle Database 11g Release 2 are:
Flashback Transaction Foreign Key Dependency Tracking
Flashback Transaction (the DBMS_FLASHBACK
.TRANSACTION_BACKOUT
procedure) with the CASCADE
option rolls back a transaction and its dependent transactions while the database remains online.
Before Oracle Database 11g Release 2, Flashback Transaction did not track foreign key dependencies. Therefore, if you tried to use Flashback Transaction with the CASCADE
option to roll back a transaction that had foreign key dependencies, you could get a foreign key violation error. The workaround was to include the foreign-key-dependent transactions in the list of transactions to roll back.
As of Oracle Database 11g Release 2, when using Flashback Transaction with the CASCADE
option, you do not have to include any dependent transactions in the list of transactions to be rolled back.
Foreign key dependency tracking for Flashback Transaction requires that you enable foreign key supplemental logging. For instructions, see "Configuring Your Database for Flashback Transaction". For information about Flashback Transaction, see "Using Flashback Transaction".
Fine-Grained Invalidation for Triggers
The Oracle Database 11g Release 1 feature "Fine-Grained Invalidation" has been extended to triggers.
Edition-Based Redefinition
Edition-based redefinition enables you to upgrade the database component of an application while it is in use, thereby minimizing or eliminating down time.
To upgrade an application while it is in use, you copy the database objects that comprise the application and redefine the copied objects in isolation. Your changes do not affect users of the application—they continue to run the unchanged application. When you are sure that your changes are correct, you make the upgraded application available to all users.
Using edition-based redefinition means using one or more of its component features. The features you use, and the down time, depend on these factors:
What kind of database objects you redefine
How available the database objects must be to users while you are redefining them
Whether you make the upgraded application available to some users while others continue to use the older version of the application
You always use the edition feature to copy the database objects and redefine the copied objects in isolation.
If you change the structure of one or more tables, you also use the feature editioning views.
If other users must be able to change data in the tables while you are changing their structure, you also use forward crossedition triggers. If the pre- and post-upgrade applications will be in ordinary use at the same time (hot rollover), you also use reverse crossedition triggers. Crossedition triggers are not a permanent part of the application—you drop them when all users are using the post-upgrade application.
For more information, see Chapter 19, "Edition-Based Redefinition."
APPLYING_CROSSEDITION_TRIGGER Function
The body of a forward crossedition trigger must handle data transformation collisions. If your collision-handling strategy depends on why the trigger is running, you can determine the reason with the function APPLYING_CROSSEDITION_TRIGGER
, which is defined in the package DBMS_STANDARD
.
For more information, see "Handling Data Transformation Collisions".
IGNORE_ROW_ON_DUPKEY_INDEX Hint
When a statement of the form INSERT
INTO
target
subquery
runs, a unique key for some rows to be inserted might collide with existing rows. Suppose that your application must ignore such collisions and insert the rows that do not collide with existing rows.
Before Oracle Database 11g Release 2, you had to write a PL/SQL program which, in a block with a NULL
handler for the DUP_VAL_ON_INDEX
exception, selected the source rows and then inserted them, one at a time, into the target.
As of Oracle Database 11g Release 2, you do not have to write a PL/SQL program. You can use the IGNORE_ROW_ON_DUPKEY_INDEX
hint in an INSERT
statement, which is easier to write and runs much faster. This hint is especially helpful when implementing crossedition triggers.
For more information, see "Handling Data Transformation Collisions".
CHANGE_DUPKEY_ERROR_INDEX Hint
When an INSERT
or UPDATE
statement runs, a unique key might collide with existing rows.
Before Oracle Database 11g Release 2, the collision caused error ORA-00001. You could tell that a collision had occurred, but you could not tell where.
As of Oracle Database 11g Release 2, you can use the CHANGE_DUPKEY_ERROR_INDEX
hint in an INSERT
or UPDATE
statement, specifying that when a unique key violation occurs for a specified index or set of columns, ORA-38911 is reported instead of ORA-00001. This hint is especially helpful when implementing crossedition triggers.
For more information, see "Handling Data Transformation Collisions".
DBMS_PARALLEL_EXECUTE Package
The DBMS_PARALLEL_EXECUTE
package enables you to incrementally update the data in a large table in parallel, in two high-level steps:
Group sets of rows in the table into smaller chunks.
Apply the desired UPDATE
statement to the chunks in parallel, committing each time you have finished processing a chunk.
This technique improves performance, reduces rollback space consumption, and reduces the number of row locks held. The DBMS_PARALLEL_EXECUTE
package is recommended whenever you are updating a lot of data; for example, when you are applying forward crossedition triggers.
For more information, see "Transforming Data from Pre- to Post-Upgrade Representation".
Internet Protocol version 6 (IPv6) Support
Internet Protocol version 6 (IPv6) supports a much larger address space than IPv4 does. An IPv6 address has 128 bits, while an IPv4 address has only 32 bits.
Applications that use network addresses might need small changes, and recompilation, to accommodate IPv6 addresses. For more information, see "Performing Network Operations in PL/SQL Subprograms".
The agent control utility, agtctl
, which starts a multithreaded extproc
agent, now accepts IPv6 addresses. For more information, see "Configuration Parameters for Multithreaded extproc Agent Control".
See Also: Oracle Database Net Services Administrator's Guide for detailed information about IPv6 support in Oracle Database |
The application development features for Oracle Database 11g Release 1 are:
Support for XA/JTA in Oracle Real Application Clusters (Oracle RAC) Environment
Oracle Database Spawns Multithreaded extproc Agent Directly by Default
WAIT Option for Data Definition Language (DDL) Statements
DDL statements require exclusive locks on internal structures. If these locks are unavailable when a DDL statement is issued, the DDL statement fails, though it might have succeeded if it had been issued subseconds later. The WAIT
option of the SQL statement LOCK
TABLE
enables a DDL statement to wait for its locks for a specified period before failing.
For more information, see "Choosing a Locking Strategy".
Binary XML Support for Oracle XML Database
Binary XML is a third way to represent an XML document. Binary XML complements, rather than replaces, the existing object-relational storage and CLOB
storage representations. Binary XML has two significant benefits:
XML operations can be significantly optimized, with or without an XML schema is available.
The internal representation of XML is the same on disk, in memory, and on wire.
As with other storage mechanisms, the details of binary XML storage are transparent to you. You continue to use XMLType
and its associated methods and operators.
For more information, see "Representing XML Data".
Metadata for SQL Operators and Functions
Metadata for SQL operators and functions is accessible through dynamic performance (V$
) views. Third-party tools can leverage SQL functions without maintaining their metadata in the application layer.
For more information, see "Metadata for SQL Operators and Functions".
Enhancements to Regular Expression SQL Functions
The regular expression SQL functions REGEXP_INSTR
and REGEXP_SUBSTR
have increased functionality. A new regular expression SQL function, REGEXP_COUNT
, returns the number of times a pattern appears in a string. These functions act the same in SQL and PL/SQL.
For more information, see "Oracle SQL Support for Regular Expressions".
Invisible Indexes
An invisible index is maintained by Oracle Database for every data manipulation language (DML) statement, but is ignored by the optimizer unless you explicitly set the parameter OPTIMIZER_USE_INVISIBLE_INDEXES
to TRUE
on a session or system level.
Making an index invisible is an alternative to making it unusable or dropping it. Using invisible indexes, you can:
Test the removal of an index before dropping it
Create invisible indexes temporarily for specialized, nonstandard operations, such as online application upgrades, without affecting the behavior of existing applications
For more information, see Oracle Database Administrator's Guide.
PL/SQL Function Result Cache
Before Oracle Database 11g Release 1, if you wanted your PL/SQL application to cache the results of a function, you had to design and code the cache and cache-management subprograms. If multiple sessions ran your application, each session had to have its own copy of the cache and cache-management subprograms. Sometimes each session had to perform the same expensive computations.
As of Oracle Database 11g Release 1, PL/SQL provides a function result cache. Because the function result cache is stored in a shared global area (SGA), it is available to any session that runs your application.
For more information, see "PL/SQL Function Result Cache".
Sequences in PL/SQL Expressions
The pseudocolumns CURRVAL
and NEXTVAL
make writing PL/SQL source code easier for you and improve runtime performance and scalability. You can use sequence_name
.CURRVAL
and sequence_name
.NEXTVAL
wherever you can use a NUMBER
expression.
See Example 6-6.
PL/Scope
PL/Scope is a compiler-driven tool that collects and organizes data about user-defined identifiers from PL/SQL source code. Because PL/Scope is a compiler-driven tool, you use it through interactive development environments (such as SQL Developer and JDeveloper), rather than directly.
PL/Scope enables the development of powerful and effective PL/Scope source code browsers that increase PL/SQL developer productivity by minimizing time spent browsing and understanding source code.
For a detailed description of PL/Scope, see Chapter 7, "Using PL/Scope."
PL/SQL Hierarchical Profiler
Nonhierarchical (flat) profilers record the time that a program spends within each subprogram—the function time or self time of each subprogram. Function time is helpful, but often inadequate. For example, it is helpful to know that a program spends 40% of its time in the subprogram INSERT_ORDER
, but it is more helpful to know which subprograms call INSERT_ORDER
often and the total time the program spends under INSERT_ORDER
(including its descendent subprograms). Hierarchical profilers provide such information.
The PL/SQL hierarchical profiler does this:
Reports the dynamic execution profile of your PL/SQL program, organized by subprogram calls
Accounts for SQL and PL/SQL execution times separately
Requires no special source or compile-time preparation
Stores results in database tables (hierarchical profiler tables) for custom report generation by integrated development environment (IDE) tools (such as SQL Developer and third-party tools)
To generate simple HTML reports from raw profiler output, you can use the plshprof
command-line utility.
Each subprogram-level summary in the dynamic execution profile includes information such as:
Number of calls to the subprogram
Time spent in the subprogram itself (function time or self time)
Time spent in the subprogram itself and in its descendent subprograms (subtree time)
Detailed parent-children information, for example:
All callers of a given subprogram (parents)
All subprograms that a given subprogram called (children)
How much time was spent in subprogram x when called from y
How many calls to subprogram x were from y
You can browse the generated HTML reports in any browser. The browser's navigational capabilities, combined with well chosen links, provide a powerful way to analyze performance of large applications, improve application performance, and lower development costs.
For a detailed description of PL/SQL hierarchical profiler, see Chapter 8, "Using the PL/SQL Hierarchical Profiler."
Query Result Change Notification
Before Oracle Database 11g Release 1, Continuous Query Notification (CQN) published only object change notifications, which result from DML or DDL changes to the objects associated with registered the queries.
As of Oracle Database 11g Release 1, CQN can also publish query result change notifications, which result from DML or DDL changes to the result set associated with the registered queries. New static data dictionary views enable you to see which queries are registered for result-set-change notifications (see "Querying CQN Registrations").
For more information, see Chapter 11, "Using Continuous Query Notification (CQN)."
Flashback Transaction
The DBMS_FLASHBACK
.TRANSACTION_BACKOUT
procedure rolls back a transaction and its dependent transactions while the database remains online. This recovery operation uses undo data to create and run the compensating transactions that return the affected data to its original state.
For more information, see "Using Flashback Transaction".
Flashback Data Archive (Oracle Total Recall)
A Flashback Data Archive provides the ability to store and track transactional changes to a record over its lifetime. It is no longer necessary to build this intelligence into the application. A Flashback Data Archive is useful for compliance with record stage policies and audit reports.
For more information, see "Using Flashback Data Archive (Oracle Total Recall)".
XA API Available Within PL/SQL
The XA interface functionality that supports transactions involving multiple resource managers, such as databases and queues, is now available within PL/SQL. You can use PL/SQL to switch and share transactions across SQL*Plus sessions and across processes.
For more information, see "Using the DBMS_XA Package".
Support for XA/JTA in Oracle Real Application Clusters (Oracle RAC) Environment
An XA transaction now spans Oracle RAC instances by default, enabling any application that uses XA to take full advantage of the Oracle RAC environment, enhancing the availability and scalability of the application.
For more information, see "Using Oracle XA with Oracle Real Application Clusters (Oracle RAC)".
Identity Code Package
The Identity Code Package provides tools to store, retrieve, encode, decode, and translate between various product or identity codes, including Electronic Product Code (EPC), in Oracle Database. The Identity Code Package provides new data types, metadata tables and views, and PL/SQL packages for storing EPC standard RFID tags or new types of RFID tags in a user table.
The Identity Code Package enables Oracle Database to recognize EPC coding schemes, to support efficient storage and component-level retrieval of EPC data, and to meet the EPCglobal Tag Data Translation 1.0 (TDT) standard that defines how to decode, encode, and translate between various EPC RFID tag representations.
The Identity Code Package also provides an extensible framework that enables you to use pre-existing coding schemes with applications that are not included in the EPC standard and adapt Oracle Database both to these older systems and to evolving identity codes that might become part of a future EPC standard.
The Identity Code Package also lets you create your own identity codes by first registering the new encoding category, registering the new encoding type, and then registering the new components associated with each new encoding type.
For more information, see Chapter 17, "Using the Identity Code Package."
Enhanced Online Index Creation and Rebuilding
Online index creation and rebuilding no longer requires a DML-blocking lock.
Before Oracle Database 11g Release 1, online index creation and rebuilding required a very short-term DML-blocking lock at the end of the rebuilding. The DML-blocking lock could cause a spike in the number of waiting DML operations, and therefore a short drop and spike of system usage. This system usage anomaly could trigger operating system alarm levels.
Embedded PL/SQL Gateway
The PL/SQL gateway enables a user-written PL/SQL subprogram to be invoked in response to a URL with parameters derived from an HTTP request. mod_plsql
is a form of the gateway that exists as a plug-in to the Oracle HTTP Server. Now the PL/SQL gateway is also embedded in the database itself. The embedded PL/SQL gateway uses the internal Oracle XML Database Listener and does not depend on the Oracle HTTP Server. You configure the embedded version of the gateway with the DBMS_EPG
package.
For more information, see "Using Embedded PL/SQL Gateway".
Oracle Database Spawns Multithreaded extproc Agent Directly by Default
When an application calls an external C procedure, either Oracle Database or Oracle Listener starts the external procedure agent, extproc
.
Before Oracle Database 11g Release 1, Oracle Listener spawned the multithreaded extproc
agent, and you defined environment variables for extproc
in the file listener
.ora
.
As of Oracle Database 11g Release 1, by default, Oracle Database spawns extproc
directly, eliminating the risk that Oracle Listener might spawn extproc
unexpectedly. This default configuration is recommended for maximum security. If you use it, you define environment variables for extproc
in the file extproc
.ora
.
For more information, including situations in which you cannot use the default configuration, see "Loading External Procedures".
Fine-Grained Invalidation
Before Oracle Database 11g Release 1, a DDL statement that changed a referenced object invalidated all of its dependents.
As of Oracle Database 11g Release 1, a DDL statement that changes a referenced object invalidates only the dependents for which either of these statements is true:
The dependent relies on the attribute of the referenced object that the DDL statement changed.
The compiled metadata of the dependent is no longer correct for the changed referenced object.
For example, if view v
selects columns c1
and c2
from table t
, a DDL statement that changes only column c3
of t
does not invalidate v
.
For more information, see "Invalidation of Dependent Objects".
In a database application, maintaining data integrity means ensuring that the data in the tables that the application manipulates conform to the appropriate business rules. A business rule specifies a condition or relationship that must always be true or must always be false. For example, a business rule might be that no employee can have a salary over $100,000 or that every employee in the EMPLOYEES
table must belong to a department in the DEPARTMENTS
table. Business rules vary from company to company, because each company defines its own policies about salaries, employee numbers, inventory tracking, and so on.
As explained in Oracle Database Concepts, there are several ways to ensure data integrity, and the one to use whenever possible is the integrity constraint (or constraint).
This chapter supplements this information:
The explanation of data integrity and constraints in Oracle Database Concepts
The information about managing constraints in Oracle Database Administrator's Guide
The syntactic and semantic information about constraints in Oracle Database SQL Language Reference
Note: This chapter applies to only to constraints on tables. Constraints on views do not help maintain data integrity or have associated indexes. Instead, they enable query rewrites on queries involving views, thereby improving performance when using materialized views and other data warehousing features.For more information about constraints on views, see Oracle Database SQL Language Reference. For information about using constraints in data warehouses, see Oracle Database Data Warehousing Guide. |
Topics:
Enforcing Business Rules with Both Constraints and Application Code
Enforcing Referential Integrity with FOREIGN KEY Constraints
Minimizing Space and Time Overhead for Indexes Associated with Constraints
Whenever possible, enforce business rules with constraints. In addition to the advantages explained in Oracle Database Concepts, constraints have the advantage of speed: Oracle Database can check that all the data in a table obeys a constraint faster than application code can do the equivalent checking.
Example 5-1 creates a table of departments, a table of employees, a constraint to enforce the rule that all values in the department table are unique, and a constraint to enforce the rule that every employee must work for a valid department.
Example 5-1 Enforcing Business Rules with Constraints
Create table of departments:
DROP TABLE dept_tab; CREATE TABLE dept_tab ( deptname VARCHAR2(20), deptno INTEGER );
Create table of employees:
DROP TABLE emp_tab; CREATE TABLE emp_tab ( empname VARCHAR2(80), empno INTEGER, deptno INTEGER );
Create constraint to enforce rule that all values in department table are unique:
ALTER TABLE dept_tab ADD PRIMARY KEY (deptno);
Create constraint to enforce rule that every employee must work for a valid department:
ALTER TABLE emp_tab ADD FOREIGN KEY (deptno) REFERENCES dept_tab(deptno);
Now, whenever you insert an employee record into emp_tab
, Oracle Database checks that its deptno
value appears in dept_tab
.
Suppose that instead of using a constraint to enforce the rule that every employee must work for a valid department, you use a trigger that queries dept_tab
to check that it contains the deptno
value of the employee record to be inserted into emp_tab
. Because the query uses consistent read (CR), it might miss uncommitted changes from other transactions. For more information about using triggers to enforce business rules, see Oracle Database Concepts.
See Also: Oracle Database SQL Language Reference for syntactic and semantic information about constraints |
Enforcing business rules with both constraints and application code is recommended when application code can determine that data values are invalid without querying tables. The application code can provide immediate feedback to the user and reduce the load on the database by preventing attempts to insert invalid data into tables.
For Example 5-2, assume that Example 5-1 was run and then this column was added to the table emp_tab
:
empgender VARCHAR2(1)
The only valid values for empgender
are 'M'
and 'F'
. When someone tries to insert a row into emp_tab
or update the value of emp_tab
.empgender
, application code can determine whether the new value for emp_tab
.empgender
is valid without querying a table. If the value is invalid, the application code can notify the user instead of trying to insert the invalid value, as in Example 5-2.
Example 5-2 Enforcing Business Rules with Both Constraints and Application Code
CREATE OR REPLACE PROCEDURE add_employee ( e_name emp_tab.empname%TYPE, e_gender emp_tab.empgender%TYPE, e_number emp_tab.empno%TYPE, e_dept emp_tab.deptno%TYPE ) AUTHID DEFINER IS BEGIN IF UPPER(e_gender) IN ('M','F') THEN INSERT INTO emp_tab VALUES (e_name, e_gender, e_number, e_dept); ELSE DBMS_OUTPUT.PUT_LINE('Gender must be M or F.'); END IF; END; / BEGIN add_employee ('Smith', 'H', 356, 20); END; /
Result:
Gender must be M or F.
When a unique or primary key constraint is enabled, Oracle Database creates an index automatically, but Oracle recommends that you create these indexes explicitly. If you want to use an index with a foreign key constraint, then you must create the index explicitly. For information about creating indexes explicitly, see Oracle Database Administrator's Guide or Oracle Database SQL Language Reference.
When a constraint can use an existing index, Oracle Database does not create an index for that constraint. Note that:
A unique or primary key constraint can use either a unique index, an entire nonunique index, or the first few columns of a nonunique index.
If a unique or primary key constraint uses a nonunique index, then no other unique or primary key constraint can use that nonunique index.
The column order in the constraint and index need not match.
The object number of the index used by a unique or primary key constraint is stored in CDEF$
.ENABLED
for that constraint. No static data dictionary view or dynamic performance view shows this information.
If an enabled unique or primary key constraint is using an index, you cannot drop only the index. To drop the index, you must either drop the constraint itself or disable the constraint and then drop the index. For information about disabling and dropping constraints, see Oracle Database Administrator's Guide.
See Also:
|
By default, a column can contain a NULL
value. To ensure that the column never contains a NULL
value, use the NOT
NULL
constraint (described in Oracle Database SQL Language Reference).
Use a NOT
NULL
constraint in both of these situations:
A column must contain a non-NULL
value.
For example, in the table HR
.EMPLOYEES
, each employee must have an employee ID. Therefore, the column HR
.EMPLOYEES
.EMPLOYEE_ID
has a NOT
NULL
constraint, and nobody can insert a new employee record into HR
.EMPLOYEES
without specifying a non-NULL
value for EMPLOYEE_ID
. You can insert a new employee record into HR
.EMPLOYEES
without specifying a salary; therefore, the column HR
.EMPLOYEES
.SALARY
does not have a NOT
NULL
constraint.
You want to allow index scans of the table, or allow an operation that requires indexing all rows.
Oracle Database indexes do not store keys whose values are all NULL
. Therefore, for the preceding kinds of operations, at least one indexed column must have a NOT
NULL
constraint.
Example 5-3 uses the SQL*Plus command DESCRIBE
to show which columns of the DEPARTMENTS
table have NOT
NULL
constraints, and then shows what happens if you try to insert NULL
values in columns that have NOT
NULL
constraints.
Example 5-3 Inserting NULL Values into Columns with NOT NULL Constraints
DESCRIBE DEPARTMENTS;
Result:
Name Null? Type ----------------------------------------- -------- ------------ DEPARTMENT_ID NOT NULL NUMBER(4) DEPARTMENT_NAME NOT NULL VARCHAR2(30) MANAGER_ID NUMBER(6) LOCATION_ID NUMBER(4)
Try to insert NULL
into DEPARTMENT_ID
column:
INSERT INTO DEPARTMENTS ( DEPARTMENT_ID, DEPARTMENT_NAME, MANAGER_ID, LOCATION_ID ) VALUES (NULL, 'Sales', 200, 1700);
Result:
VALUES (NULL, 'Sales', 200, 1700) * ERROR at line 4: ORA-01400: cannot insert NULL into ("HR"."DEPARTMENTS"."DEPARTMENT_ID")
Omitting a value for a column that cannot be NULL
is the same as assigning it the value NULL
:
INSERT INTO DEPARTMENTS ( DEPARTMENT_NAME, MANAGER_ID, LOCATION_ID ) VALUES ('Sales', 200, 1700);
Result:
INSERT INTO DEPARTMENTS ( * ERROR at line 1: ORA-01400: cannot insert NULL into ("HR"."DEPARTMENTS"."DEPARTMENT_ID")
You can prevent the preceding error by giving DEPARTMENT_ID
a non-NULL
default value. For more information, see "When to Use Default Column Values".
You can combine NOT
NULL
constraints with other constraints to further restrict the values allowed in specific columns. For example, the combination of NOT
NULL
and UNIQUE
constraints forces the input of values in the UNIQUE
key, eliminating the possibility that data in a new conflicts with data in an existing row. For more information, see "UNIQUE and NOT NULL Constraints on the Foreign Key".
When an INSERT
statement (described in Oracle Database SQL Language Reference) does not specify a value for a specific column, that column receives its default value. By default, that default value is NULL
. You can change the default value when you define the column (with the CREATE
TABLE
statement, described in Oracle Database SQL Language Reference) or when you alter the column (with the ALTER
TABLE
statement, described in Oracle Database SQL Language Reference).
Note: Giving a column a non-NULL default value does not ensure that the value of the column will never have the value NULL , as the NOT NULL constraint does. For information about the NOT NULL constraint, see "When to Use NOT NULL Constraints". |
Use a default column value in these situations:
The column has a NOT
NULL
constraint.
Giving the column a non-NULL
default value prevents the error that would occur if someone inserted a row without specifying a value for the column.
There is a most common value for the column.
For example, if most departments in the company are in New York, then set the default value of the column DEPARTMENTS
.LOCATION
to 'NEW YORK'
.
There is a non-NULL
value that signifies no entry.
For example, if the value zero in the column EMPLOYEES
.SALARY
means that the salary has not yet been determined, then set the default value of that column to zero.
A default column value that signifies no entry can simplify testing. For example, it lets you change this test:
IF (employees.salary IS NOT NULL) AND (employees.salary < 50000)
To this test:
IF employees.salary < 50000
You want to automatically record the names of users who modify a table.
For example, suppose that you allow users to insert rows into a table through a view. You give the base table a column named inserter
(which need not be included in the definition of the view), to store the name of the user who inserted the row. To record the user name automatically, define a default value that invokes the USER
function. For example:
CREATE TABLE audit_trail (
value1 NUMBER,
value2 VARCHAR2(32),
inserter VARCHAR2(30) DEFAULT USER
);
The primary key of a table uniquely identifies each row and ensures that no duplicate rows exist (and typically, this is its only purpose). Therefore, a primary key value cannot be NULL
.
A table can have at most one primary key, but that key can have multiple columns (that is, it can be a composite key). To designate a primary key, use the PRIMARY
KEY
constraint.
Whenever practical, choose as the primary key a single column whose values are generated by a sequence. For information about sequences, see Oracle Database SQL Language Reference.
The second-best choice for a primary key is a single column whose values are all of the following:
Unique
Never changed
Never NULL
Short and numeric (and therefore easy to type)
Minimize your use of composite primary keys, whose values are long and cannot be generated by a sequence.
See Also:
|
Use a UNIQUE
constraint (which designates a unique key) on any column or combination of columns (except the primary key) where duplicate non-NULL
values are not allowed. For example:
Unique Key | Primary Key |
---|---|
Employee Social Security Number | Employee number |
Truck license plate number | Truck number |
Customer phone number (country code column, area code column, and local phone number column) | Customer number |
Department name column and location column | Department number |
Figure 5-1 shows a table with a UNIQUE
constraint, a row that violates the constraint, and a row that satisfies it.
Figure 5-1 Rows That Violate and Satisfy a UNIQUE Constraint
See Also:
|
When two tables share one or more columns, you use can use a FOREIGN
KEY
constraint to enforce referential integrity—that is, to ensure that the shared columns always have the same values in both tables.
Note: AFOREIGN KEY constraint is also called a referential integrity constraint, and its CONSTRAINT_TYPE is R in the static data dictionary views *_CONSTRAINTS . |
Designate one table as the referenced or parent table and the other as the dependent or child table. In the parent table, define either a PRIMARY
KEY
or UNIQUE
constraint on the shared columns. In the child table, define a FOREIGN
KEY
constraint on the shared columns. The shared columns now comprise a foreign key. Defining additional constraints on the foreign key affects the parent-child relationship—for details, see "Defining Relationships Between Parent and Child Tables".
Figure 5-2 shows a foreign key defined on the department number. It guarantees that every value in this column must match a value in the primary key of the department table. This constraint prevents erroneous department numbers from getting into the employee table.
Figure 5-2 shows parent and child tables that share one column, a row that violates the FOREIGN
KEY
constraint, and a row that satisfies it.
Figure 5-2 Rows That Violate and Satisfy a FOREIGN KEY Constraint
Topics:
See Also:
|
Foreign keys allow key values that are all NULL
, even if there are no matching PRIMARY
or UNIQUE
keys.
By default (without any NOT
NULL
or CHECK
clauses), the FOREIGN
KEY
constraint enforces the match none rule for composite foreign keys in the ANSI/ISO standard.
To enforce the match full rule for NULL
values in composite foreign keys, which requires that all components of the key be NULL
or all be non-null, define a CHECK
constraint that allows only all nulls or all non-nulls in the composite foreign key. For example, with a composite key comprised of columns A
, B
, and C
:
CHECK ((A IS NULL AND B IS NULL AND C IS NULL) OR (A IS NOT NULL AND B IS NOT NULL AND C IS NOT NULL))
In general, it is not possible to use declarative referential integrity to enforce the match partial rule for NULL
values in composite foreign keys, which requires the non-null portions of the key to appear in the corresponding portions in the primary or unique key of a single row in the referenced table. You can often use triggers to handle this case, as described in Oracle Database PL/SQL Language Reference.
Several relationships between parent and child tables can be determined by the other types of constraints defined on the foreign key in the child table.
No Constraints on the Foreign Key When no other constraints are defined on the foreign key, any number of rows in the child table can reference the same parent key value. This model allows nulls in the foreign key.
This model establishes a one-to-many relationship between the parent and foreign keys that allows undetermined values (nulls) in the foreign key. An example of such a relationship is shown in Figure 5-2 between the employee
and department
tables. Each department (parent key) has many employees (foreign key), and some employees might not be in a department (nulls in the foreign key).
NOT NULL Constraint on the Foreign Key When nulls are not allowed in a foreign key, each row in the child table must explicitly reference a value in the parent key because nulls are not allowed in the foreign key.
Any number of rows in the child table can reference the same parent key value, so this model establishes a one-to-many relationship between the parent and foreign keys. However, each row in the child table must have a reference to a parent key value; the absence of a value (a null) in the foreign key is not allowed. The same example in the previous section illustrates such a relationship. However, in this case, employees must have a reference to a specific department.
UNIQUE Constraint on the Foreign Key When a UNIQUE
constraint is defined on the foreign key, only one row in the child table can reference a given parent key value. This model allows nulls in the foreign key.
This model establishes a one-to-one relationship between the parent and foreign keys that allows undetermined values (nulls) in the foreign key. For example, assume that the employee table had a column named MEMBERNO
, referring to an employee membership number in the company insurance plan. Also, a table named INSURANCE
has a primary key named MEMBERNO
, and other columns of the table keep respective information relating to an employee insurance policy. The MEMBERNO
in the employee table must be both a foreign key and a unique key:
To enforce referential integrity rules between the EMP_TAB
and INSURANCE
tables (the FOREIGN KEY
constraint)
To guarantee that each employee has a unique membership number (the UNIQUE
key constraint)
UNIQUE and NOT NULL Constraints on the Foreign Key When both UNIQUE
and NOT
NULL
constraints are defined on the foreign key, only one row in the child table can reference a given parent key value, and because NULL
values are not allowed in the foreign key, each row in the child table must explicitly reference a value in the parent key.
This model establishes a one-to-one relationship between the parent and foreign keys that does not allow undetermined values (nulls) in the foreign key. If you expand the previous example by adding a NOT
NULL
constraint on the MEMBERNO
column of the employee table, in addition to guaranteeing that each employee has a unique membership number, you also ensure that no undetermined values (nulls) are allowed in the MEMBERNO
column of the employee table.
Oracle Database allows a column to be referenced by multiple FOREIGN
KEY
constraints; there is no limit on the number of dependent keys. This situation might be present if a single column is part of two different composite foreign keys.
When Oracle Database checks a constraint, it signals an error if the constraint is not satisfied. To defer checking constraints until the end of the current transaction, use the SET
CONSTRAINTS
statement.
Note: You cannot use theSET CONSTRAINTS statement inside a trigger. |
When deferring constraint checks:
Select appropriate data.
You might want to defer constraint checks on UNIQUE
and FOREIGN
keys if the data you are working with has any of these characteristics:
Tables are snapshots.
Some tables contain a large amount of data being manipulated by another application, which might not return the data in the same order.
Update cascade operations on foreign keys.
Ensure that constraints are deferrable.
After identifying the appropriate tables, ensure that their FOREIGN
, UNIQUE
and PRIMARY
key constraints are created DEFERRABLE
.
Within the application that manipulates the data, set all constraints deferred before you begin processing any data, as follows:
SET CONSTRAINTS ALL DEFERRED;
(Optional) Check for constraint violations immediately before committing the transaction.
Immediately before the COMMIT
statement, run the SET
CONSTRAINTS
ALL
IMMEDIATE
statement. If there are any problems with a constraint, this statement fails, and identifies the constraint that caused the error. If you commit while constraints are violated, the transaction rolls back and you get an error message.
In Example 5-4, the PRIMARY
and FOREIGN
keys of the table emp
are created DEFERRABLE
and then deferred.
Example 5-4 Deferring Constraint Checks
DROP TABLE dept; CREATE TABLE dept ( deptno NUMBER PRIMARY KEY, dname VARCHAR2 (30) ); DROP TABLE emp; CREATE TABLE emp ( empno NUMBER, ename VARCHAR2(30), deptno NUMBER, CONSTRAINT pk_emp_empno PRIMARY KEY (empno) DEFERRABLE, CONSTRAINT fk_emp_deptno FOREIGN KEY (deptno) REFERENCES dept(deptno) DEFERRABLE ); INSERT INTO dept (deptno, dname) VALUES (10, 'Accounting'); INSERT INTO dept (deptno, dname) VALUES (20, 'SALES'); INSERT INTO emp (empno, ename, deptno) VALUES (1, 'Corleone', 10); INSERT INTO emp (empno, ename, deptno) VALUES (2, 'Costanza', 20); COMMIT; SET CONSTRAINTS ALL DEFERRED; UPDATE dept SET deptno = deptno + 10 WHERE deptno = 20;
Query:
SELECT * from dept ORDER BY deptno;
Result:
DEPTNO DNAME ---------- ------------------------------ 10 Accounting 30 SALES 2 rows selected.
Update:
UPDATE emp SET deptno = deptno + 10 WHERE deptno = 20;
Result:
1 row updated.
Query:
SELECT * from emp ORDER BY deptno;
Result:
EMPNO ENAME DEPTNO ---------- ------------------------------ ---------- 1 Corleone 10 2 Costanza 30 2 rows selected.
The SET
CONSTRAINTS
applies only to the current transaction, and its setting lasts for the duration of the transaction, or until another SET
CONSTRAINTS
statement resets the mode. The ALTER
SESSION
SET
CONSTRAINTS
statement applies only for the current session. The defaults specified when you create a constraint remain while the constraint exists.
See Also: Oracle Database SQL Language Reference for more information about theSET CONSTRAINTS statement |
When you create a UNIQUE
or PRIMARY
key, Oracle Database checks to see if an existing index enforces uniqueness for the constraint. If there is no such index, the database creates one.
When Oracle Database uses a unique index to enforce a constraint, and constraints associated with the unique index are dropped or disabled, the index is dropped. To preserve the statistics associated with the index (which would take a long time to re-create), specify the KEEP
INDEX
clause on the DROP
CONSTRAINT
statement.
While enabled foreign keys reference a PRIMARY
or UNIQUE
key, you cannot disable or drop the PRIMARY
or UNIQUE
key constraint or the index.
Note: UNIQUE and PRIMARY keys with deferrable constraints must all use nonunique indexes. |
To use existing indexes when creating unique and primary key constraints, include USING
INDEX
in the CONSTRAINT
clause. For details and examples, see Oracle Database SQL Language Reference.
Index foreign keys unless the matching unique or primary key is never updated or deleted.
The declaration of a referential constraint cannot specify a foreign key that references a primary or unique key of a remote table.
However, you can maintain parent/child table relationships across nodes using triggers.
See Also: Oracle Database PL/SQL Language Reference for more information about triggers that enforce referential integrity |
Note: If you decide to define referential integrity across the nodes of a distributed database using triggers, be aware that network failures can make both the parent table and the child table inaccessible.For example, assume that the child table is in the If the network connection between the two databases fails, then some data manipulation language (DML) statements against the child table (those that insert rows or update a foreign key value) cannot proceed, because the referential integrity triggers must have access to the parent table in the |
Use CHECK
constraints when you must enforce integrity rules based on logical expressions, such as comparisons. Never use CHECK
constraints when any of the other types of constraints can provide the necessary checking.
Examples of CHECK
constraints include:
A CHECK
constraint on employee salaries so that no salary value is greater than 10000.
A CHECK
constraint on department locations so that only the locations "BOSTON
", "NEW
YORK
", and "DALLAS
" are allowed.
A CHECK
constraint on the salary and commissions columns to prevent the commission from being larger than the salary.
A CHECK
constraint requires that a condition be true or unknown for every row of the table. If a statement causes the condition to evaluate to false, then the statement is rolled back. The condition of a CHECK
constraint has these limitations:
The condition must be a boolean expression that can be evaluated using the values in the row being inserted or updated.
The condition cannot contain subqueries or sequences.
The condition cannot include the SYSDATE
, UID
, USER
, or USERENV
SQL functions.
The condition cannot contain the pseudocolumns LEVEL
or ROWNUM
.
The condition cannot contain the PRIOR
operator.
The condition cannot contain a user-defined function.
See Also:
|
When using CHECK
constraints, remember that a CHECK
constraint is violated only if the condition evaluates to false; true and unknown values (such as comparisons with nulls) do not violate a check condition. Ensure that any CHECK
constraint that you define is specific enough to enforce the rule.
For example, consider this CHECK
constraint:
CHECK (Sal > 0 OR Comm >= 0)
At first glance, this rule may be interpreted as "do not allow a row in the employee table unless the employee salary is greater than zero or the employee commission is greater than or equal to zero." But if a row is inserted with a null salary, that row does not violate the CHECK
constraint, regardless of whether the commission value is valid, because the entire check condition is evaluated as unknown. In this case, you can prevent such violations by placing NOT
NULL
constraints on both the SAL
and COMM
columns.
Note: If you are not sure when unknown values result inNULL conditions, review the truth tables for the logical conditions in Oracle Database SQL Language Reference |
A single column can have multiple CHECK
constraints that reference the column in its definition. There is no limit to the number of CHECK
constraints that can be defined that reference a column.
The order in which the constraints are evaluated is not defined, so be careful not to rely on the order or to define multiple constraints that conflict with each other.
According to the ANSI/ISO standard, a NOT
NULL
constraint is an example of a CHECK
constraint, where the condition is:
CHECK (column_name IS NOT NULL)
Therefore, you can write NOT
NULL
constraints for a single column using either a NOT
NULL
constraint or a CHECK
constraint. The NOT
NULL
constraint is easier to use than the CHECK
constraint.
In the case where a composite key can allow only all nulls or all values, you must use a CHECK
constraint. For example, this CHECK
constraint allows a key value in the composite key made up of columns C1
and C2
to contain either all nulls or all values:
CHECK ((C1 IS NULL AND C2 IS NULL) OR (C1 IS NOT NULL AND C2 IS NOT NULL))
Example 5-5 and Example 5-6 show how to create simple constraints during the prototype phase of your database design. In these examples, each constraint is given a name. Naming the constraints prevents the database from creating multiple copies of the same constraint, with different system-generated names, if the data definition language (DDL) statement runs multiple times.
Example 5-5 creates tables and their constraints at the same time, using the CREATE
TABLE
statement.
Example 5-5 Defining Constraints with the CREATE TABLE Statement
DROP TABLE DeptTab; CREATE TABLE DeptTab ( Deptno NUMBER(3) CONSTRAINT pk_DeptTab_Deptno PRIMARY KEY, Dname VARCHAR2(15), Loc VARCHAR2(15), CONSTRAINT u_DeptTab_Dname_Loc UNIQUE (Dname, Loc), CONSTRAINT c_DeptTab_Loc CHECK (Loc IN ('NEW YORK', 'BOSTON', 'CHICAGO'))); DROP TABLE EmpTab; CREATE TABLE EmpTab ( Empno NUMBER(5) CONSTRAINT pk_EmpTab_Empno PRIMARY KEY, Ename VARCHAR2(15) NOT NULL, Job VARCHAR2(10), Mgr NUMBER(5) CONSTRAINT r_EmpTab_Mgr REFERENCES EmpTab, Hiredate DATE, Sal NUMBER(7,2), Comm NUMBER(5,2), Deptno NUMBER(3) NOT NULL CONSTRAINT r_EmpTab_DeptTab REFERENCES DeptTab ON DELETE CASCADE);
Example 5-6 creates constraints for existing tables, using the ALTER
TABLE
statement.
You cannot create a validated constraint on a table if the table contains rows that violate the constraint.
Example 5-6 Defining Constraints with the ALTER TABLE Statement
-- Create tables without constraints: DROP TABLE DeptTab; CREATE TABLE DeptTab ( Deptno NUMBER(3), Dname VARCHAR2(15), Loc VARCHAR2(15) ); DROP TABLE EmpTab; CREATE TABLE EmpTab ( Empno NUMBER(5), Ename VARCHAR2(15), Job VARCHAR2(10), Mgr NUMBER(5), Hiredate DATE, Sal NUMBER(7,2), Comm NUMBER(5,2), Deptno NUMBER(3) ); --Define constraints with the ALTER TABLE statement: ALTER TABLE DeptTab ADD CONSTRAINT pk_DeptTab_Deptno PRIMARY KEY (Deptno); ALTER TABLE EmpTab ADD CONSTRAINT fk_DeptTab_Deptno FOREIGN KEY (Deptno) REFERENCES DeptTab; ALTER TABLE EmpTab MODIFY (Ename VARCHAR2(15) NOT NULL);
See Also: Oracle Database Administrator's Guide for information about creating and maintaining constraints for a large production database |
The creator of a constraint must have the ability to create tables (the CREATE
TABLE
or CREATE
ANY
TABLE
system privilege), or the ability to alter the table (the ALTER
object privilege for the table or the ALTER
ANY
TABLE
system privilege) with the constraint. Additionally, UNIQUE
and PRIMARY
KEY
constraints require that the owner of the table have either a quota for the tablespace that contains the associated index or the UNLIMITED
TABLESPACE
system privilege. FOREIGN
KEY
constraints also require some additional privileges.
Assign names to constraints NOT
NULL
, UNIQUE
, PRIMARY
KEY
, FOREIGN
KEY
, and CHECK
using the CONSTRAINT
option of the constraint clause. This name must be unique among the constraints that you own. If you do not specify a constraint name, one is assigned automatically by Oracle Database.
Choosing your own name makes error messages for constraint violations more understandable, and prevents the creation of duplicate constraints with different names if the SQL statements are run more than once.
See the previous examples of the CREATE
TABLE
and ALTER
TABLE
statements for examples of the CONSTRAINT
option of the constraint
clause. The name of each constraint is included with other information about the constraint in the data dictionary.
This section explains the mechanisms and procedures for manually enabling and disabling constraints.
enabled constraint. When a constraint is enabled, the corresponding rule is enforced on the data values in the associated columns. The definition of the constraint is stored in the data dictionary.
disabled constraint. When a constraint is disabled, the corresponding rule is not enforced. The definition of the constraint is still stored in the data dictionary.
An integrity constraint represents an assertion about the data in a database. This assertion is always true when the constraint is enabled. The assertion might not be true when the constraint is disabled, because data that violates the integrity constraint can be in the database.
Topics:
During day-to-day operations, keep constraints enabled. In certain situations, temporarily disabling the constraints of a table makes sense for performance reasons. For example:
When loading large amounts of data into a table using SQL*Loader
When performing batch operations that make massive changes to a table (such as changing each employee number by adding 1000 to the existing number)
When importing or exporting one table at a time
Temporarily turning off constraints can speed up these operations.
When you define an integrity constraint (using either CREATE
TABLE
or ALTER
TABLE
), Oracle Database enables the constraint by default. For code clarity, you can explicitly enable the constraint by including the ENABLE
clause in its definition, as in Example 5-7.
Example 5-7 Creating Enabled Constraints
/* Use CREATE TABLE statement to create enabled constraint (ENABLE keyword is optional): */ DROP TABLE t1; CREATE TABLE t1 (Empno NUMBER(5) PRIMARY KEY ENABLE); /* Create table without constraint and then use ALTER TABLE statement to add enabled constraint (ENABLE keyword is optional): */ DROP TABLE t2; CREATE TABLE t2 (Empno NUMBER(5)); ALTER TABLE t2 ADD PRIMARY KEY (Empno) ENABLE;
Include the ENABLE
clause when defining a constraint for a table to be populated a row at a time by individual transactions. This ensures that data is always consistent, and reduces the performance overhead of each DML statement.
An ALTER
TABLE
statement that tries to enable an integrity constraint fails if an existing row of the table violates the integrity constraint. The statement rolls back and the constraint definition is neither stored nor enabled.
You define and disable an integrity constraint (using either CREATE
TABLE
or ALTER
TABLE
), by including the DISABLE
clause in its definition, as in Example 5-8.
Example 5-8 Creating Disabled Constraints
/* Use CREATE TABLE statement to create disabled constraint */ DROP TABLE t1; CREATE TABLE t1 (Empno NUMBER(5) PRIMARY KEY DISABLE); /* Create table without constraint and then use ALTER TABLE statement to add disabled constraint */ DROP TABLE t2; CREATE TABLE t2 (Empno NUMBER(5)); ALTER TABLE t2 ADD PRIMARY KEY (Empno) DISABLE;
Include the DISABLE
clause when defining a constraint for a table to have large amounts of data inserted before anybody else accesses it, particularly if you must cleanse data after inserting it, or must fill empty columns with sequence numbers or parent/child relationships.
An ALTER
TABLE
statement that defines and disables a constraint never fails, because its rule is not enforced.
After you have cleansed the data and filled the empty columns, you can enable constraints that were disabled during data insertion.
To enable an existing constraint, use the ALTER
TABLE
statement with the ENABLE
clause, as in Example 5-9.
Example 5-9 Enabling Existing Constraints
-- Create table with disabled constraints: DROP TABLE DeptTab; CREATE TABLE DeptTab ( Deptno NUMBER(3) PRIMARY KEY DISABLE, Dname VARCHAR2(15), Loc VARCHAR2(15), CONSTRAINT uk_DeptTab_Dname_Loc UNIQUE (Dname, Loc) DISABLE, CONSTRAINT c_DeptTab_Loc CHECK (Loc IN ('NEW YORK', 'BOSTON', 'CHICAGO')) DISABLE ); -- Enable constraints: ALTER TABLE DeptTab ENABLE PRIMARY KEY ENABLE CONSTRAINT uk_DeptTab_Dname_Loc ENABLE CONSTRAINT c_DeptTab_Loc;
An ALTER
TABLE
statement that attempts to enable an integrity constraint fails if any of the table rows violate the integrity constraint. The statement is rolled back and the constraint is not enabled.
If you must perform a large insert or update when a table contains data, you can temporarily disable constraints to improve performance of the bulk operation.
To disable an existing constraint, use the ALTER
TABLE
statement with the DISABLE
clause, as in Example 5-10.
Example 5-10 Disabling Existing Constraints
-- Create table with enabled constraints: DROP TABLE DeptTab; CREATE TABLE DeptTab ( Deptno NUMBER(3) PRIMARY KEY ENABLE, Dname VARCHAR2(15), Loc VARCHAR2(15), CONSTRAINT uk_DeptTab_Dname_Loc UNIQUE (Dname, Loc) ENABLE, CONSTRAINT c_DeptTab_Loc CHECK (Loc IN ('NEW YORK', 'BOSTON', 'CHICAGO')) ENABLE ); -- Disable constraints: ALTER TABLE DeptTab DISABLE PRIMARY KEY DISABLE CONSTRAINT uk_DeptTab_Dname_Loc DISABLE CONSTRAINT c_DeptTab_Loc;
When enabling or disabling UNIQUE
, PRIMARY
KEY
, and FOREIGN
KEY
constraints, be aware of several important issues and prerequisites. UNIQUE
key and PRIMARY
KEY
constraints are usually managed by the database administrator.
If a row of a table disobeys an integrity constraint, then this row is in violation of the constraint and is called an exception to the constraint. If any exceptions exist, then the constraint cannot be enabled. The rows that violate the constraint must be updated or deleted before the constraint can be enabled.
You can identify exceptions for a specific integrity constraint as you try to enable the constraint.
When you try to create or enable a constraint, and the statement fails because integrity constraint exceptions exist, the statement is rolled back. You cannot enable the constraint until all exceptions are either updated or deleted. To determine which rows violate the integrity constraint, include the EXCEPTIONS
option in the ENABLE
clause of a CREATE
TABLE
or ALTER
TABLE
statement.
See Also: Oracle Database Administrator's Guide for more information about responding to constraint exceptions |
Starting with Oracle8i, you can modify an existing constraint with the MODIFY
CONSTRAINT
clause, as in Example 5-11.
See Also: Oracle Database SQL Language Reference for information about the parameters you can modify |
Example 5-11 Modifying Constraints
/* Create & then modify a CHECK constraint: */ DROP TABLE X1Tab; CREATE TABLE X1Tab ( a1 NUMBER CONSTRAINT c_X1Tab_a1 CHECK (a1>3) DEFERRABLE DISABLE ); ALTER TABLE X1Tab MODIFY CONSTRAINT c_X1Tab_a1 ENABLE; ALTER TABLE X1Tab MODIFY CONSTRAINT c_X1Tab_a1 RELY; ALTER TABLE X1Tab MODIFY CONSTRAINT c_X1Tab_a1 INITIALLY DEFERRED; ALTER TABLE X1Tab MODIFY CONSTRAINT c_X1Tab_a1 ENABLE NOVALIDATE; /* Create & then modify a PRIMARY KEY constraint: */ DROP TABLE t1; CREATE TABLE t1 (a1 INT, b1 INT); ALTER TABLE t1 ADD CONSTRAINT pk_t1_a1 PRIMARY KEY(a1) DISABLE; ALTER TABLE t1 MODIFY PRIMARY KEY INITIALLY IMMEDIATE USING INDEX PCTFREE = 30 ENABLE NOVALIDATE; ALTER TABLE t1 MODIFY PRIMARY KEY ENABLE NOVALIDATE;
One property of a constraint that you can modify is its name. Situations in which you would rename a constraint include:
You want to clone a table and its constraints.
Constraint names must be unique, even across multiple schemas. Therefore, the constraints in the original table cannot have the same names as those in the cloned table.
You created a constraint with a default system-generated name, and now you want to give it a name that is easy to remember, so that you can easily enable and disable it.
Example 5-12 shows how to find the system-generated name of a constraint and change it.
Example 5-12 Renaming a Constraint
DROP TABLE T; CREATE TABLE T ( C1 NUMBER PRIMARY KEY, C2 NUMBER );
Query:
SELECT CONSTRAINT_NAME FROM USER_CONSTRAINTS WHERE TABLE_NAME = 'T' AND CONSTRAINT_TYPE = 'P';
Result (system-generated name of constraint name varies):
CONSTRAINT_NAME
------------------------------
SYS_C0013059
1 row selected.
Rename constraint from name reported in preceding query to T_C1_PK
:
ALTER TABLE T RENAME CONSTRAINT SYS_C0013059 TO T_C1_PK;
Query:
SELECT CONSTRAINT_NAME FROM USER_CONSTRAINTS WHERE TABLE_NAME = 'T' AND CONSTRAINT_TYPE = 'P';
Result:
CONSTRAINT_NAME ------------------------------ T_C1_PK 1 row selected.
You can drop a constraint using the DROP
clause of the ALTER
TABLE
statement. Situations in which you would drop a constraint include:
The constraint enforces a rule that is no longer true.
The constraint is no longer needed.
To drop a constraint and all other integrity constraints that depend on it, specify CASCADE
.
Example 5-13 Dropping Constraints
-- Create table with constraints: DROP TABLE DeptTab; CREATE TABLE DeptTab ( Deptno NUMBER(3) PRIMARY KEY, Dname VARCHAR2(15), Loc VARCHAR2(15), CONSTRAINT uk_DeptTab_Dname_Loc UNIQUE (Dname, Loc), CONSTRAINT c_DeptTab_Loc CHECK (Loc IN ('NEW YORK', 'BOSTON', 'CHICAGO')) ); -- Drop constraints: ALTER TABLE DeptTab DROP PRIMARY KEY DROP CONSTRAINT uk_DeptTab_Dname_Loc DROP CONSTRAINT c_DeptTab_Loc;
When dropping UNIQUE
, PRIMARY
KEY
, and FOREIGN
KEY
constraints, be aware of several important issues and prerequisites. UNIQUE
and PRIMARY
KEY
constraints are usually managed by the database administrator.
See Also:
|
FOREIGN
KEY
constraints enforce relationships between columns in different tables. Therefore, they cannot be enabled if the constraint of the referenced primary or unique key is not present or not enabled.
You must use the same data type for corresponding columns in the dependent and referenced tables. The column names need not match.
Because foreign keys reference primary and unique keys of the parent table, and PRIMARY
KEY
and UNIQUE
key constraints are enforced using indexes, composite foreign keys are limited to 32 columns.
If the column list is not included in the REFERENCES
option when defining a FOREIGN
KEY
constraint (single column or composite), then Oracle Database assumes that you intend to reference the primary key of the specified table. Alternatively, you can explicitly specify the column(s) to reference in the parent table within parentheses. Oracle Database automatically checks to verify that this column list references a primary or unique key of the parent table. If it does not, then an informative error is returned.
To create a FOREIGN
KEY
constraint, the creator of the constraint must have privileged access to the parent and child tables.
Parent Table The creator of the referential integrity constraint must own the parent table or have REFERENCES
object privileges on the columns that constitute the parent key of the parent table.
Child Table The creator of the referential integrity constraint must have the ability to create tables (that is, the CREATE
TABLE
or CREATE
ANY
TABLE
system privilege) or the ability to alter the child table (that is, the ALTER
object privilege for the child table or the ALTER
ANY
TABLE
system privilege).
In both cases, necessary privileges cannot be obtained through a role; they must be explicitly granted to the creator of the constraint.
These restrictions allow:
The owner of the child table to explicitly decide which constraints are enforced and which other users can create constraints
The owner of the parent table to explicitly decide if foreign keys can depend on the primary and unique keys in her tables
Oracle Database allows different types of referential integrity actions to be enforced, as specified with the definition of a FOREIGN
KEY
constraint:
Prevent Delete or Update of Parent Key The default setting prevents the deletion or update of a parent key if there is a row in the child table that references the key. For example:
CREATE TABLE Emp_tab ( FOREIGN KEY (Deptno) REFERENCES Dept_tab);
Delete Child Rows When Parent Key Deleted The ON
DELETE
CASCADE
action allows parent key data that is referenced from the child table to be deleted, but not updated. When data in the parent key is deleted, all rows in the child table that depend on the deleted parent key values are also deleted. To specify this referential action, include the ON
DELETE
CASCADE
option in the definition of the FOREIGN
KEY
constraint. For example:
CREATE TABLE Emp_tab ( FOREIGN KEY (Deptno) REFERENCES Dept_tab ON DELETE CASCADE);
Set Foreign Keys to Null When Parent Key Deleted The ON
DELETE
SET
NULL
action allows data that references the parent key to be deleted, but not updated. When referenced data in the parent key is deleted, all rows in the child table that depend on those parent key values have their foreign keys set to null. To specify this referential action, include the ON
DELETE
SET
NULL
option in the definition of the FOREIGN
KEY
constraint. For example:
CREATE TABLE Emp_tab ( FOREIGN KEY (Deptno) REFERENCES Dept_tab ON DELETE SET NULL);
To find the names of constraints, what columns they affect, and other information to help you manage them, query the static data dictionary views *_CONSTRAINTS
and *_CONS_COLUMNS
, as in Example 5-14.
Example 5-14 Viewing Information About Constraints
DROP TABLE DeptTab; CREATE TABLE DeptTab ( Deptno NUMBER(3) PRIMARY KEY, Dname VARCHAR2(15), Loc VARCHAR2(15), CONSTRAINT uk_DeptTab_Dname_Loc UNIQUE (Dname, Loc), CONSTRAINT c_DeptTab_Loc CHECK (Loc IN ('NEW YORK', 'BOSTON', 'CHICAGO')) ); DROP TABLE EmpTab; CREATE TABLE EmpTab ( Empno NUMBER(5) PRIMARY KEY, Ename VARCHAR2(15) NOT NULL, Job VARCHAR2(10), Mgr NUMBER(5) CONSTRAINT r_EmpTab_Mgr REFERENCES EmpTab ON DELETE CASCADE, Hiredate DATE, Sal NUMBER(7,2), Comm NUMBER(5,2), Deptno NUMBER(3) NOT NULL CONSTRAINT r_EmpTab_Deptno REFERENCES DeptTab ); -- Format columns (optional): COLUMN CONSTRAINT_NAME FORMAT A20; COLUMN CONSTRAINT_TYPE FORMAT A4 HEADING 'TYPE'; COLUMN TABLE_NAME FORMAT A10; COLUMN R_CONSTRAINT_NAME FORMAT A17; COLUMN SEARCH_CONDITION FORMAT A40; COLUMN COLUMN_NAME FORMAT A12;
List accessible constraints in DeptTab and EmpTab:
SELECT CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME, R_CONSTRAINT_NAME FROM USER_CONSTRAINTS WHERE (TABLE_NAME = 'DEPTTAB' OR TABLE_NAME = 'EMPTAB') ORDER BY CONSTRAINT_NAME;
Result:
CONSTRAINT_NAME TYPE TABLE_NAME R_CONSTRAINT_NAME -------------------- ---- ---------- ----------------- C_DEPTTAB_LOC C DEPTTAB R_EMPTAB_DEPTNO R EMPTAB SYS_C006286 R_EMPTAB_MGR R EMPTAB SYS_C006290 SYS_C006286 P DEPTTAB SYS_C006288 C EMPTAB SYS_C006289 C EMPTAB SYS_C006290 P EMPTAB UK_DEPTTAB_DNAME_LOC U DEPTTAB 8 rows selected.
Distinguish between NOT
NULL
and CHECK
constraints in DeptTab
and EmpTab
:
SELECT CONSTRAINT_NAME, SEARCH_CONDITION FROM USER_CONSTRAINTS WHERE (TABLE_NAME = 'DEPTTAB' OR TABLE_NAME = 'EMPTAB') AND CONSTRAINT_TYPE = 'C' ORDER BY CONSTRAINT_NAME;
Result:
CONSTRAINT_NAME SEARCH_CONDITION -------------------- ---------------------------------------- C_DEPTTAB_LOC Loc IN ('NEW YORK', 'BOSTON', 'CHICAGO') SYS_C006288 "ENAME" IS NOT NULL SYS_C006289 "DEPTNO" IS NOT NULL 3 rows selected.
For DeptTab
and EmpTab
, list columns that constitute constraints:
SELECT CONSTRAINT_NAME, TABLE_NAME, COLUMN_NAME FROM USER_CONS_COLUMNS WHERE (TABLE_NAME = 'DEPTTAB' OR TABLE_NAME = 'EMPTAB') ORDER BY CONSTRAINT_NAME;
Result:
CONSTRAINT_NAME TABLE_NAME COLUMN_NAME -------------------- ---------- ------------ C_DEPTTAB_LOC DEPTTAB LOC R_EMPTAB_DEPTNO EMPTAB DEPTNO R_EMPTAB_MGR EMPTAB MGR SYS_C006286 DEPTTAB DEPTNO SYS_C006288 EMPTAB ENAME SYS_C006289 EMPTAB DEPTNO SYS_C006290 EMPTAB EMPNO UK_DEPTTAB_DNAME_LOC DEPTTAB LOC UK_DEPTTAB_DNAME_LOC DEPTTAB DNAME 9 rows selected.
Note that:
Some constraint names are user specified (such as UK_DEPTTAB_DNAME_LOC
), while others are system specified (such as SYS_C006290
).
Each constraint type is denoted with a different character in the CONSTRAINT_TYPE
column. This table summarizes the characters used for each constraint type:
Constraint Type | Character |
---|---|
PRIMARY KEY | P |
UNIQUE KEY | U |
FOREIGN KEY | R |
CHECK , NOT NULL | C |
Note: An additional constraint type is indicated by the character "V " in the CONSTRAINT_TYPE column. This constraint type corresponds to constraints created using the WITH CHECK OPTION for views. |
These constraints are explicitly listed in the SEARCH_CONDITION
column:
NOT
NULL
constraints
The conditions for user-defined CHECK
constraints
Advanced Application Developer's Guide
11g Release 2 (11.2)
E25518-05
April 2012
Oracle Database Advanced Application Developer's Guide, 11g Release 2 (11.2)
E25518-05
Copyright © 1996, 2012, Oracle and/or its affiliates. All rights reserved.
Primary Author: Sheila Moore
Contributing Authors: D. Adams, L. Ashdown, M. Cowan, T. Kyte, J. Melnick, R. Moran, E. Paapanen, J. Russell, R. Strohm, R. Ward
Contributors: D. Alpern, G. Arora, C. Barclay, D. Bronnikov, T. Chang, L. Chen, B. Cheng, M. Davidson, R. Day, R. Decker, G. Doherty, D. Elson, A. Ganesh, M. Hartstein, Y. Hu, J. Huang, C. Iyer, N. Jain, R. Jenkins Jr., S. Kotsovolos, V. Krishnaswamy, S. Kumar, C. Lei, B. Llewellyn, D. Lorentz, V. Moore, K. Muthukkaruppan, V. Moore, J. Muller, R. Murthy, R. Pang, B. Sinha, S. Vemuri, W. Wang, D. Wong, A. Yalamanchi, Q. Yu
This software and related documentation are provided under a license agreement containing restrictions on use and disclosure and are protected by intellectual property laws. Except as expressly permitted in your license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform, publish, or display any part, in any form, or by any means. Reverse engineering, disassembly, or decompilation of this software, unless required by law for interoperability, is prohibited.
The information contained herein is subject to change without notice and is not warranted to be error-free. If you find any errors, please report them to us in writing.
If this is software or related documentation that is delivered to the U.S. Government or anyone licensing it on behalf of the U.S. Government, the following notice is applicable:
U.S. GOVERNMENT RIGHTS Programs, software, databases, and related documentation and technical data delivered to U.S. Government customers are "commercial computer software" or "commercial technical data" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, the use, duplication, disclosure, modification, and adaptation shall be subject to the restrictions and license terms set forth in the applicable Government contract, and, to the extent applicable by the terms of the Government contract, the additional rights set forth in FAR 52.227-19, Commercial Computer Software License (December 2007). Oracle America, Inc., 500 Oracle Parkway, Redwood City, CA 94065.
This software or hardware is developed for general use in a variety of information management applications. It is not developed or intended for use in any inherently dangerous applications, including applications that may create a risk of personal injury. If you use this software or hardware in dangerous applications, then you shall be responsible to take all appropriate fail-safe, backup, redundancy, and other measures to ensure its safe use. Oracle Corporation and its affiliates disclaim any liability for any damages caused by use of this software or hardware in dangerous applications.
Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.
Intel and Intel Xeon are trademarks or registered trademarks of Intel Corporation. All SPARC trademarks are used under license and are trademarks or registered trademarks of SPARC International, Inc. AMD, Opteron, the AMD logo, and the AMD Opteron logo are trademarks or registered trademarks of Advanced Micro Devices. UNIX is a registered trademark of The Open Group.
This software or hardware and documentation may provide access to or information on content, products, and services from third parties. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to third-party content, products, and services. Oracle Corporation and its affiliates will not be responsible for any loss, costs, or damages incurred due to your access to or use of third-party content, products, or services.
This chapter explains how to develop applications on the publish-subscribe model.
Topics:
Because the database is the most significant resource of information within the enterprise, Oracle created a publish-subscribe solution for enterprise information delivery and messaging to complement this role.
Networking technologies and products enable a high degree of connectivity across a large number of computers, applications, and users. In these environments, it is important to provide asynchronous communications for the class of distributed systems that operate in a loosely-coupled and autonomous fashion, and which require operational immunity from network failures. This requirement is filled by various middleware products that are characterized as messaging, message-oriented middleware (MOM), message queuing, or publish-subscribe.
Applications that communicate through a publish and subscribe paradigm require the sending applications (publishers) to publish messages without explicitly specifying recipients or having knowledge of intended recipients. Similarly, receiving applications (subscribers) must receive only those messages that the subscriber has registered an interest in.
This decoupling between senders and recipients is usually accomplished by an intervening entity between the publisher and the subscriber, which serves as a level of indirection. This intervening entity is a queue that represents a subject or channel. Figure 16-1 illustrates publish and subscribe functionality.
Figure 16-1 Oracle Publish-Subscribe Functionality
A subscriber subscribes to a queue by expressing interest in messages enqueued to that queue and by using a subject- or content-based rule as a filter. This results in a set of rule-based subscriptions associated with a given queue.
At run time, publishers post messages to various queues. The queue (in other words, the delivery mechanisms of the underlying infrastructure) then delivers messages that match the various subscriptions to the appropriate subscribers.
Oracle Database includes these features to support database-enabled publish-subscribe messaging:
Database events support declarative definitions for publishing database events, detection, and runtime publication of such events. This feature enables active publication of information to end-users in an event-driven manner, to complement the traditional pull-oriented approaches to accessing information.
Oracle Advanced Queuing (AQ) supports a queue-based publish-subscribe paradigm. Database queues serve as a durable store for messages, along with capabilities to allow publish and subscribe based on queues. A rules-engine and subscription service dynamically route messages to recipients based on expressed interest. This allows decoupling of addressing between senders and receivers to complement the existing explicit sender-receiver message addressing.
Client notifications support asynchronous delivery of messages to interested subscribers, enabling database clients to register interest in certain queues, and it enables these clients to receive notifications when publications on such queues occur. Asynchronous delivery of messages to database clients is in contrast to the traditional polling techniques used to retrieve information.
A queue is an entity that supports the notion of named subjects of interest. Queues can be characterized as persistent or nonpersistent (lightweight).
A persistent queue serves as a durable container for messages. Messages are delivered in a deferred and reliable mode.
The underlying infrastructure of a nonpersistent, or lightweight, queue pushes the messages published to connected clients in a lightweight, at-best-once, manner.
Publishers and subscribers are internally represented as agents.
An agent is a persistent logical subscribing entity that expresses interest in a queue through a subscription. An agent has properties, such as an associated subscription, an address, and a delivery mode for messages. In this context, an agent is an electronic proxy for a publisher or subscriber.
client
A client is a transient physical entity. The attributes of a client include the physical process where the client programs run, the node name, and the client application logic. Several clients can act on behalf of a single agent. The same client, if authorized, can act on behalf of multiple agents.
A rule on a queue is specified as a conditional expression using a predefined set of operators on the message format attributes or on the message header attributes. Each queue has an associated message content format that describes the structure of the messages represented by that queue. The message format may be unstructured (RAW
) or it may have a well-defined structure (ADT). This allows both subject- or content-based subscriptions.
Subscribers (agents) may specify subscriptions on a queue using a rule. Subscribers are durable and are stored in a catalog.
database event publication framework
The database represents a significant source for publishing information. An event framework is proposed to allow declarative definition of database event publication. As these pre-defined events occur, the framework detects and publishes such events. This allows active delivery of information to end-users in an event-driven manner as part of the publish-subscribe capability.
Registration is the process of associated delivery information by a given client, acting on behalf of an agent. There is an important distinction between the subscription and registration related to the agent/client separation.
Subscription indicates an interest in a particular queue by an agent. It does not specify where and how delivery must occur. Delivery information is a physical property that is associated with a client, and it is a transient manifestation of the logical agent (the subscriber). A specific client process acting on behalf of an agent registers delivery information by associating a host and port, indicating where the delivery is to be done, and a callback, indicating how there delivery is to be done.
publishing a message
Publishers publish messages to queues by using the appropriate queuing interfaces. The interfaces may depend on which model the queue is implemented on. For example, an enqueue call represents the publishing of a message.
When a message is posted or published to a given queue, a rules engine extracts the set of candidate rules from all rules defined on that queue that match the published message.
Corresponding to the list of candidate rules on a given queue, the set of subscribers that match the candidate rules can be evaluated. In turn, the set of agents corresponding to this subscription list can be determined and notified.
posting
The queue notifies all registered clients of the appropriate published messages. This concept is called posting. When the queue must notify all interested clients, it posts the message to all registered clients.
receiving a message
A subscriber may receive messages through any of these mechanisms:
A client process acting on behalf of the subscriber specifies a callback using the registration mechanism. The posting mechanism then asynchronously invokes the callback when a message matches the subscriber's subscription. The message content may be passed to the callback function (nonpersistent queues only).
A client process acting on behalf of the subscriber specifies a callback using the registration mechanism. The posting mechanism then asynchronously invokes the callback function, but without the full message content. This serves as a notification to the client, which subsequently retrieves the message content in a pull fashion (persistent queues only).
A client process acting on behalf of the subscriber simply retrieves messages from the queue in a periodic, or some other appropriate, manner. While the messages are deferred, there is no asynchronous delivery to the end-client.
This example shows how database events, client notification, and AQ work to implement publish-subscribe.
Create under the user schema, pubsub
, with all objects necessary to support a publish-subscribe mechanism. In this particular code, the Agent snoop
subscribe to messages that are published at logon events. To use AQ functionality, user pubsub
needs AQ_ADMINISTRATOR_ROLE
privileges and EXECUTE
privilege on DBMS_AQ
and DBMS_AQADM
.
Rem ------------------------------------------------------ REM create queue table for persistent multiple consumers: Rem ------------------------------------------------------ Rem Create or replace a queue table BEGIN DBMS_AQADM.CREATE_QUEUE_TABLE( Queue_table => 'Pubsub.Raw_msg_table', Multiple_consumers => TRUE, Queue_payload_type => 'RAW', Compatible => '8.1'); END; / Rem ------------------------------------------------------ Rem Create a persistent queue for publishing messages: Rem ------------------------------------------------------ Rem Create a queue for logon events BEGIN DBMS_AQADM.CREATE_QUEUE( Queue_name => 'Pubsub.Logon', Queue_table => 'Pubsub.Raw_msg_table', Comment => 'Q for error triggers'); END; / Rem ------------------------------------------------------ Rem Start the queue: Rem ------------------------------------------------------ BEGIN DBMS_AQADM.START_QUEUE('pubsub.logon'); END; / Rem ------------------------------------------------------ Rem define new_enqueue for convenience: Rem ------------------------------------------------------ CREATE OR REPLACE PROCEDURE New_enqueue( Queue_name IN VARCHAR2, Payload IN RAW , Correlation IN VARCHAR2 := NULL, Exception_queue IN VARCHAR2 := NULL) AS Enq_ct DBMS_AQ.Enqueue_options_t; Msg_prop DBMS_AQ.Message_properties_t; Enq_msgid RAW(16); Userdata RAW(1000); BEGIN Msg_prop.Exception_queue := Exception_queue; Msg_prop.Correlation := Correlation; Userdata := Payload; DBMS_AQ.ENQUEUE(Queue_name, Enq_ct, Msg_prop, Userdata, Enq_msgid); END; / Rem ------------------------------------------------------ Rem add subscriber with rule based on current user name, Rem using correlation_id Rem ------------------------------------------------------ DECLARE Subscriber Sys.Aq$_agent; BEGIN Subscriber := sys.aq$_agent('SNOOP', NULL, NULL); DBMS_AQADM.ADD_SUBSCRIBER( Queue_name => 'Pubsub.logon', Subscriber => subscriber, Rule => 'CORRID = ''HR'' '); END; / Rem ------------------------------------------------------ Rem create a trigger on logon on database: Rem ------------------------------------------------------ Rem create trigger on after logon: CREATE OR REPLACE TRIGGER pubsub.Systrig2 AFTER LOGON ON DATABASE BEGIN New_enqueue('Pubsub.Logon', HEXTORAW('9999'), Dbms_standard.login_user); END; /
After subscriptions are created, the next step is for the client to register for notification using callback functions. This is done using the Oracle Call Interface (OCI). This code performs necessary steps for registration. The initial steps of allocating and initializing session handles are omitted here for sake of clarity:
ub4 namespace = OCI_SUBSCR_NAMESPACE_AQ; /* callback function for notification of logon of user 'HR' on database: */ ub4 notifySnoop(ctx, subscrhp, pay, payl, desc, mode) dvoid *ctx; OCISubscription *subscrhp; dvoid *pay; ub4 payl; dvoid *desc; ub4 mode; { printf("Notification : User HR Logged on\n"); } int main() { OCISession *authp = (OCISession *) 0; OCISubscription *subscrhpSnoop = (OCISubscription *)0; /***************************************************** Initialize OCI Process/Environment Initialize Server Contexts Connect to Server Set Service Context ******************************************************/ /* Registration Code Begins */ /* Each call to initSubscriptionHn allocates and Initialises a Registration Handle */ initSubscriptionHn( &subscrhpSnoop, /* subscription handle */ "ADMIN:PUBSUB.SNOOP", /* subscription name */ /* <agent_name>:<queue_name> */ (dvoid*)notifySnoop); /* callback function */ /***************************************************** The Client Process does not need a live Session for Callbacks End Session and Detach from Server ******************************************************/ OCISessionEnd ( svchp, errhp, authp, (ub4) OCI_DEFAULT); /* detach from server */ OCIServerDetach( srvhp, errhp, OCI_DEFAULT); while (1) /* wait for callback */ sleep(1); } void initSubscriptionHn (subscrhp, subscriptionName, func) OCISubscription **subscrhp; char* subscriptionName; dvoid * func; { /* allocate subscription handle: */ (void) OCIHandleAlloc((dvoid *) envhp, (dvoid **)subscrhp, (ub4) OCI_HTYPE_SUBSCRIPTION, (size_t) 0, (dvoid **) 0); /* set subscription name in handle: */ (void) OCIAttrSet((dvoid *) *subscrhp, (ub4) OCI_HTYPE_SUBSCRIPTION, (dvoid *) subscriptionName, (ub4) strlen((char *)subscriptionName), (ub4) OCI_ATTR_SUBSCR_NAME, errhp); /* set callback function in handle: */ (void) OCIAttrSet((dvoid *) *subscrhp, (ub4) OCI_HTYPE_SUBSCRIPTION, (dvoid *) func, (ub4) 0, (ub4) OCI_ATTR_SUBSCR_CALLBACK, errhp); (void) OCIAttrSet((dvoid *) *subscrhp, (ub4) OCI_HTYPE_SUBSCRIPTION, (dvoid *) 0, (ub4) 0, (ub4) OCI_ATTR_SUBSCR_CTX, errhp); /* set namespace in handle: */ (void) OCIAttrSet((dvoid *) *subscrhp, (ub4) OCI_HTYPE_SUBSCRIPTION, (dvoid *) &namespace, (ub4) 0, (ub4) OCI_ATTR_SUBSCR_NAMESPACE, errhp); checkerr(errhp, OCISubscriptionRegister(svchp, subscrhp, 1, errhp, OCI_DEFAULT)); }
If user HR
logs on to the database, the client is notified, and the call back function notifySnoop
is invoked.