Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 50 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
50
Dung lượng
177,98 KB
Nội dung
CREATE TABLE pets OF Pet_t
(PRIMARY KEY (tag_no))
NESTED TABLE vaccinations STORE AS
pet_vaccinations_tab;
Using this separate persons table and the REF attribute will allow the existence of people outside the
context of their pets (something the pet-obsessed may not envision, but probably a good idea from a
design point of view). In this context, REF is called a type modifier.
Does a REF sound a lot like a foreign key? While there are important differences between REFs and
foreign keys (see
Table 18.2), Oracle actually claims that REFs, are "more reliable and persistent"
than foreign keys probably because REFs do not refer to user-changeable values, but rather to
invisible internal values.
In fact, the problem with REFs is that they are too persistent. Oracle currently allows you to delete an
object that is the target of a REF without deleting the reference to it. They even dignify this state with
a name: a dangling REF. This is roughly equivalent to what would happen if you delete a department
record without changing the records of employees in that department. There is no declarative way to
prevent dangling REFs, but it should not be too challenging to do so by implementing pre-delete
triggers on the table that contains the "parent" objects.[11] To make life somewhat easier, Oracle
provides a predicate, IS DANGLING, to test for this condition:
[11] It is also possible to use a foreign key in combination with a REF. To do so, you
would include an attribute for the foreign key in the Pet_t specification and include a
FOREIGN KEY clause in the CREATE TABLE statement.
UPDATE pets
SET owner_ref = NULL
WHERE owner_ref IS DANGLING;
Table 18.2: Chief Differences between Foreign Keys and REFs
Characteristic Foreign Key REF
Who defines the value used as the
"pointer?"
User (programmer) System
Requirements on the parent Must have primary or unique
key
Must be an object table or
object view
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Only allows insertions of child if
parent exists (or if the referencing
columns are null)?
Yes, when enabled Yes, since you can only
insert a "real" REF
Can be defined in such a way that
the child may be associated with
one of several possible parents?
No (although foreign keys have
a little-known ability to point to
all of several possible parents)
Yes; by default, a REF
can refer to any row
object of the given type
Can declaratively restrict the scope
of the child so that it can point to
only one given parent table?
No Yes (by using the SCOPE
clause in the CREATE
TABLE command)
Restricts updates of the parent key
when children exist?
Yes Yes; object identifiers are
not updateable
Can prevent the deletion of parent
if children exist?
Yes No
Can cascade deletions of the parent
to child (objects)?
Yes, with ON DELETE
CASCADE
No
Default type of relationship
between parent and child when
joined via SQL
Equi-join Outer join (when using
dot navigation)
Parent and child can be on
different databases?
No; must be enforced with table-
level triggers
Not in Oracle 8.0.3
NOTE: In
Table 18.2, we use the terminology "parent" and "child" only for
convenience; these terms are not always accurate descriptions of objects linked via
REFs.
Oracle has a special syntax for retrieving and modifying data in both SQL and PL/SQL using the
REF operator; they also provide a DEREF operator (can you guess why?). We'll look at those
operators a bit later.
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Previous: 18.1 Introduction
to Oracle8 Objects
Oracle PL/SQL
Programming, 2nd Edition
Next: 18.3 Syntax for
Creating Object Types
18.1 Introduction to Oracle8
Objects
Book Index
18.3 Syntax for Creating
Object Types
The Oracle Library
Navigation
Copyright (c) 2000 O'Reilly & Associates. All rights reserved.
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Previous: 18.2 Oracle
Objects Example
Chapter 18
Object Types
Next: 18.4 Manipulating
Objects in PL/SQL and
SQL
18.3 Syntax for Creating Object Types
This section explains the syntax for CREATE TYPE, CREATE TYPE BODY, and some of the other
statements you will use when working with Oracle objects.
18.3.1 About Object Types
A given object type can have all of the following:
● One default constructor method
● Zero or one comparison methods
● Any number of member methods
The default constructor, supplied automatically when you create an object type, allows you to create
an object of the corresponding type. You have no direct control over this function (aside from how
you have defined the attributes of the object type). The constructor is the only type of method that
does not operate on an existing object.
Comparison methods are either MAP or ORDER methods (see
Section 18.3.6, "Comparing Objects"
later in this chapter). They allow you to establish rules so that SQL statements and PL/SQL programs
can order, group, and otherwise compare object instances. Comparison methods are always functions.
Member methods are either member functions or member procedures. These are where programmers
define the bulk of the object's behavior.
18.3.2 CREATE TYPE and DROP TYPE: Creating and Dropping Types
The CREATE TYPE statement has the following general format:
CREATE [ OR REPLACE ] TYPE <type name> AS OBJECT
<attribute name> datatype, ,
MEMBER PROCEDURE | FUNCTION <procedure or function
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
spec>, ,
[ MAP | ORDER MEMBER FUNCTION <comparison function
spec>, ]
[ PRAGMA RESTRICT_REFERENCES (<what to restrict>,
restrictions) ]
);
As you would expect, you can drop a type using a DROP statement as follows:
DROP TYPE <type name> [ FORCE ] ;
Parameters have the following meanings:
OR REPLACE
Tells Oracle that you want to rebuild the type if it should happen to already exist. This will
preserve grants. (See "Schema Evolution" later in the chapter for information about the effect
this option has on the object type's metadata.)
type name
A legal Oracle identifier that isn't already in use by any other Oracle database object such as
another type, table, or package. May be expressed in "schema dot" notation (e.g., SCOTT.
foo).
attribute name
A legal PL/SQL identifier for the attribute.
datatype
Any legal Oracle datatype except LONG, LONG RAW, NCHAR, NCLOB, NVARCHAR2,
ROWID, BINARY_INTEGER, BOOLEAN, PLS_INTEGER, RECORD, REF CURSOR, %
TYPE, %ROWTYPE, or types that exist only within packages.
comparison function
Defines a function that allows comparison of object values.
what to restrict
This is either the name of the function or procedure, or the keyword DEFAULT. Using
DEFAULT tells Oracle that all member functions and procedures in the object type will have
the designated restrictions, without having to list each one in its own
RESTRICT_REFERENCES pragma.
restrictions
One or more of the following: RNDS, WNDS, RNPS, and WNPS (see
Chapter 17).
FORCE++
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Tells Oracle that you want to drop a type even if there are other objects with dependencies on
it. Even if you use FORCE, you can only drop a type if it has not been implemented in a table;
you must first drop the table(s) before dropping the type.
Notice that the syntax for creating the specification is merely a comma-separated list of attributes and
methods. There are no semicolons as you would find in a package specification.
You cannot impose NOT NULL or DEFAULT constraints at the attribute level. These constraints
can, however, be applied to scalar attributes if you create an object table based on type. The syntax is:
CREATE TABLE <table name> OF <object type name>
(<column constraint>, );
For example:
CREATE TABLE foos OF Foo_t
(bar NOT NULL);
or, if you wish to name a constraint:
CREATE TABLE foos OF Foo_t
(CONSTRAINT bar_not_null CHECK (bar IS NOT NULL));
18.3.3 CREATE TYPE BODY: Creating a Body
The syntax for the CREATE TYPE BODY statement is the following:
CREATE [ OR REPLACE ] TYPE BODY <type name> AS | IS (
MEMBER PROCEDURE | FUNCTION <procedure or function
body>, ,
[ MAP | ORDER MEMBER FUNCTION <comparison function
body> ]
END;
Strictly speaking, type bodies are optional; you need a body only if you have created any methods in
the specification. Similar to the rules for package specifications and bodies, the methods declared in
the specification must match one for one the methods implemented in the body. Methods can be
overloaded (see
Chapter 15), and the standard rules about overloading apply.
18.3.4 Dot Notation
Even if you don't use the object extensions to Oracle, dot notation can be confusing. In SQL, for
example, you may have references such as basil.meals.calories, referring to a column called calories
in a meals table owned by basil. Add in remote database references, and you might get something like
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
basil.meals.calories@mktg.ny.acme.com. In PL/SQL Version 2 and up, dots are found in record
datatypes, table datatype operators, packaged procedure or function references, and elsewhere.
In the objects option, there are at least two new opportunities to get confused with dots: object data
structures and object methods. (And the discussion below ignores the fact that object names can be
preceded by the schema name, as in schema_name.object_name.)
18.3.4.1 Dots in data structures
In a PL/SQL program, you can refer to object attributes with dot notation, as in object_name.
attribute_name. For example, after declaring and initializing an object my_pet of type Pet_t, we can
do this:
IF my_pet.sex = 'M' THEN
This variable means "the sex attribute of the object instance my_pet."
Referring to nested objects in PL/SQL using dot notation is almost intuitive, as long as you're using
embedded objects (that is, the attribute is an object itself, not a REF to an object).
CREATE OBJECT Pet_t (
owner Person_t, embedded object, not a REF
);
DECLARE
the_dalmatian Pet_t;
BEGIN
IF the_dalmatian.owner.first_name = 'Persephone'
THEN
The IF test above simply checks whether the first name of the owner of the Dalmatian is Persephone.
In SQL statements, you can also use dots to navigate the components of nested objects. Even when
you have nested objects with REFs, SQL graciously allows you to navigate to the referenced object
without actually doing a join:
CREATE OBJECT Pet_t (
owner_ref REF Person_t,
);
CREATE TABLE pets of Pet_t;
SELECT name, p.owner_ref.first_name
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
FROM pets p;
That's a pretty neat trick. No ugly join clause, just an intuitive "do the right thing" call. It works for
attributes and member functions that are defined with the appropriate RESTRICT_REFERENCES
pragma. But what do we do in PL/SQL? Is this legal?
DECLARE
the_dalmatian Pet_t;
BEGIN
SELECT VALUE(p) INTO the_dalmatian
FROM pets p
WHERE name = 'Cerberus';
IF the_dalmatian.owner_ref.first_name = 'Persephone'
invalid
THEN
It won't work! In Oracle 8.0.3, you cannot navigate the database through PL/SQL REF variables.
Repeat this to yourself like a mantra. Dot notation doesn't help us in this case. For now, you can
instead use DEREF, described in detail later on; a future version of Oracle will likely include a built-
in package called UTL_REF that supports navigation in PL/SQL.
18.3.4.2 Dots in method invocations
When you invoke an object's member function or procedure, the dot syntax is straightforward, as in
the following:
object_instance_name.function_name (args)
object_instance_name.procedure_name (args)
If you want to use the output from one method as the input to another, you don't have to use a
temporary variable. You can actually chain methods together with dots, as long as they are type
compatible:
object_name.function_name(args).function_name(args).
procedure_name(args)
Before we can take a look at an example that chains our Pet_t methods, we'll want to change the
specification of print_me. Instead of using the default IN OUT mode of the SELF parameter in a
member procedure, we are going to make it an IN. That is, instead of:
MEMBER PROCEDURE print_me
we want to use:
MEMBER PROCEDURE print_me (SELF IN Pet_t)
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
(Remember that we have to make this change in both the object type specification and the object type
body.)
Why did we make the change? The default IN OUT mode can only accept a SELF parameter that is
writeable, and function return values are never writeable. But as an IN-only parameter, SELF can
now accept a Pet_t object that is returned from one of the other functions.
DECLARE
the_pet Pet_t := Pet_t(1949,'Godzilla','BIG
MONKEY','M',
NULL,NULL,NULL);
BEGIN
the_pet.set_tag_no(1948).set_photo('gz105.jpg').
print_me();
END;
This means "change the tag number of the pet variable to 1948, change its photo to gz105.jpg, and
print the result." If you give a little thought to the implications of this convenience feature, you'll
realize that it could be valuable to define member functions which return the base object type, so that
you can chain them together later.
Here are some rules about chaining:
● Methods are invoked in order from left to right.
● The return value of a chained method must be of the object type expected by the method to its
right.
● A chained call can include at most a single procedure.
● If your chained call includes a procedure, it must be the right-most method in the chain.
● Be sure that you don't try to use a function's return value (which is read-only) as an IN OUT
input to the next method in the chain.
18.3.4.3 Attribute or method?
In PL/SQL, there is no automatic visual distinction between an object attribute and an object method
unless the method has arguments. That is, in this code fragment:
IF my_pet.whatever = 'a value' THEN
we can't immediately determine if "whatever" is an attribute or a method! In some cases, this
ambiguity could be a feature, since one day we might want to replace an attribute by a method of the
same name.
If we want to make our code less mysterious, we can add a trailing empty parameter list to method
calls which have no parameters, as in the following:
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
my_pet.print_me();
The empty parentheses notation works for both member functions and member procedures.
NOTE: The situation is different in SQL statements. If you call a member function
without parameters in a SQL statement, you must use empty parentheses notation. That
is, if somefun is a function, don't do this:
SELECT p.somefun FROM pets p; invalid
The statement above fails with an ORA-00904, "invalid column name." The correct
syntax is:
SELECT p.somefun() FROM pets p;
18.3.5 SELF: The Implied Parameter
Because a method can only be called within the context of a particular object instance, it always has
an object of the corresponding type as a "parameter." This makes sense because the method will
(almost) always need access to that object's attributes. This implied parameter is called SELF. By
default, SELF is an IN parameter in member functions, and an IN OUT parameter in member
procedures.
If we create an object to hold American Kennel Club papers:
CREATE TYPE Akc_paper_t AS OBJECT(
pet_ref REF Pet_t,
issued_on DATE,
contents BLOB);
the following member function specifications are equivalent:
MEMBER FUNCTION print_me RETURN BOOLEAN;
MEMBER FUNCTION print_me (SELF Akc_paper_t) RETURN
BOOLEAN;
MEMBER FUNCTION print_me (SELF IN Akc_paper_t) RETURN
BOOLEAN;
Similarly, member procedure SELF parameters default to IN OUT, so the following are equivalent to
one another:
MEMBER PROCEDURE reissue;
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
[...]... database like Oracle could implement an invoker rights model for object methods As with all new technology, we will simply have to wait and see whether such a change Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark comes about, and if it does, what sort of impact it will have on existing applications Previous: 18.2 Oracle Objects Example 18.2 Oracle Objects Example Oracle PL/SQL... ever used an arbitrary number (maybe an Oracle sequence) as a table's primary key? The benefits are many chief among them that you can often hide it from the users and never have to worry about them wanting to change the key value! Object identifiers are a lot like your arbitrary numbers, except that they are assigned by Oracle When you create a table of objects, Oracle adds a hidden field that will... large series of objects, while an ORDER method is more useful if you are comparing two objects 18.3.6.2 Equality comparisons If you don't create a MAP or ORDER method, Oracle allows you to test only for equality of two different objects Two Oracle objects are "equal" if and only if they (1) are of the same object type; and (2) both have attributes with identical values Object attributes get compared one... equality comparisons work only if the object table contains attributes that Oracle knows how to compare For example, they will work on objects with scalar attributes, but they will not work on objects with collection attributes, embedded object types, REFs, or LOBs Also, if you create a MAP or ORDER member function, you override Oracle' s ability to perform the default equality test by comparing all the... categories of users to whom object privileges may be granted, programmers and end users, there is only one Oracle privilege that applies to object types: EXECUTE Let's look at how this privilege applies to DDL (typically for programmers) and DML (typically for end users) 18.3.7.1 DDL Let's say that you are the Oracle user named SCOTT and you have created an object type Pet_t You want to grant JOE permission... in Oracle7 Whenever I execute the package, I am actually using the owner's privileges on tables, views, and the like I need no privileges on the underlying structures This definer rights model can be very useful in encapsulating the table data and protecting it from change except through the package As mentioned earlier in the chapter (see the Sidebar called "Encapsulation of Persistent Objects in Oracle" ),... features within the language Now, if we are taking an object-oriented approach, it would be useful if Oracle allowed statements such as the following: IF my_pet > your_pet THEN my_pet and your_pet are objects SELECT FROM pets ORDER BY owner; object column owner is an But it is not at all obvious how Oracle would deal with statements like these Should it do some sort of "munching" average on the objects'... objects' attributes, or what? Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark In fact, Oracle allows us to formulate our own comparison rules for the object types we create By defining a special MAP or ORDER member function when we define an object type, we can tell Oracle how to compare objects of that type in both PL/SQL and SQL expressions 18.3.6.1 The MAP and ORDER methods... that they are assigned by Oracle When you create a table of objects, Oracle adds a hidden field that will hold the object identifier for each object Oracle also automatically creates a unique index on this column When you insert an object into the table, Oracle automatically assigns the object a rather large but hidden object identifier (OID) The OID is: q q Opaque Although your programs can indirectly... name of the column where Oracle8 .0.3 stores object identifiers is SYS_NC_OID$ This column is "hidden" in that you won't see it when you "describe" the table in SQL*Plus, but it exists for every object instance (row) in an object table It contains a 16-byte binary value; although this value is selectable from SQL*Plus, it should never be stored or manipulated in your programs Oracle has Please purchase . Introduction
to Oracle8 Objects
Oracle PL/SQL
Programming, 2nd Edition
Next: 18.3 Syntax for
Creating Object Types
18.1 Introduction to Oracle8
Objects
Book.
Previous: 18.2 Oracle
Objects Example
Oracle PL/SQL
Programming, 2nd Edition
Next: 18.4 Manipulating
Objects in PL/SQL and
SQL
18.2 Oracle Objects