Tải bản đầy đủ (.pdf) (10 trang)

Oracle SQL Plus The Definitive Guide- P24A docx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (96.21 KB, 10 trang )

< previous page page_198 next page >
Page 198
SET PAGESIZE 14
SET LONG 80
SET LINESIZE 80
Notes about the LIST_COLUMNS script
The first part of the script simply initializes a few settings and clears any previously existing column and break settings.
The next part of the script, which is a bit more complex, breaks the first argument up so the owner's name and the table
name are in separate substitution variables. The script is intended to be invoked like this:
@LIST_COLUMNS [owner. ] table_name
The first argument, referenced by &&1, will contain a table name that is possibly qualified with an owner name. The
first task of the script is to interpret this first argument. The following DECODE statement will return the table owner, if
one was specified:
DECODE(INSTR(&&1,.),
0,USER, /*Default to current user.*/
UPPER(SUBSTR(&&1,1,INSTR(&&1,.)-1))) owner_name,
If no period is contained in the argument, then no owner name was explicitly specified, and DECODE will call the
USER function to return the name of the currently logged on user. If a table owner was specified, the position of the
period will be non-zero, causing DECODE to return the value of the last expression, which uses SUBSTR to return all
characters before the period as the owner. A similar approach is taken to get the table name:
DECODE(INSTR(&&1,.),
0,UPPER(&&1), /*Only the table name was passed in.*/
UPPER (SUBSTR (&&1, INSTR(&&1,.)+1))) table_name
The issue here is that if a period was specified, the table name follows the period. Otherwise, the entire string is taken as
the table name. The table name and owner name are selected from the DUAL table in order to get them into the
substitution variables s_table_name and s_owner_name. The NEW_VALUE clause of the COLUMN command makes
this happen.
The next part of the script is the SELECT statement, which returns information about each column in the table. The
only complicated part of this query is the DECODE statement that starts out like this:
DECODE (data_type,
VARCHAR2, VARCHAR2 ( ¦¦ TO_CHAR(data_length) ¦¦ ),


NVARCHAR2, NVARCHAR2 ( ¦¦ TO_CHAR(data_length) ¦¦ ),
CHAR, CHAR ( ¦¦ TO_CHAR(data_length) ¦¦ ),
NCHAR, NCHAR ( ¦¦ TO_CHAR(data_length) ¦¦ ) ,
NUMBER,
DECODE (data_precision,

< previous page page_198 next page >
< previous page page_199 next page >
Page 199
NULL, NUMBER,
NUMBER ( ¦¦ TO_CHAR(data_precision) ¦¦ , ¦¦ TO_CHAR(data_scale) ¦¦ )),

The long DECODE expression exists because some datatypes have a length associated with them, some have a
precision and scale, and some have neither. This DECODE statement contains one expression for each possible
datatype, and that expression returns the appropriate information for that datatype. Consider the VARCHAR2 datatype,
for example. All VARCHAR2 columns have a length associated with them. In order to display that length, the
following two expressions are included in the DECODE statement:
VARCHAR2, VARCHAR2 ( ¦¦ TO_CHAR(data_length) ¦¦ )
The two expressions are separated by commas. The first expression evaluates to the string VARCHAR2. When
DECODE is evaluating a datatype that matches that string, it will return the value of the second expression in the pair.
In the case of VARCHAR2, that second expression is:
VARCHAR2 ( ¦¦ TO_CHAR(data_length) ¦¦ )
As you can see, this second expression concatenates the string VARCHAR2 ( with the length, then follows that with a
closing parentheses. The result will be a string resembling the one shown here:
VARCHAR2 (40)
The NUMBER and FLOAT datatypes add a bit more complexity. A NUMBER, for example, can be defined as floating-
point or fixed-point. Floating-point numbers have null values for data_precision and data_scale. If a NUMBER field is
floating-point, the data_precision will be null, and the nested DECODE will return just NUMBER as the datatype.
Otherwise, the nested DECODE will return NUMBER (precision, scale).
A second SELECT is done to return any default values defined for columns in the table. This is done in a separate query

primarily because some versions of SQL*Plus delivered with early versions of Oracle8 (notably 8.0.3) generated errors
whenever a LONG column contained a null value. The query in the preceding script avoids this problem by specifying
WHERE data_default IS NOT NULL in the WHERE clause.
Running List_Columns
To run LIST_COLUMNS, execute the script from SQL*Plus and specify the table name as a command-line argument.
You may optionally qualify the table name with an owner by using standard dot notation. The following example shows
how to list columns for a table you own.

< previous page page_199 next page >
< previous page page_200 next page >
Page 200
SQL> @list_columns employee

COLUMN LISTING FOR JEFF.EMPLOYEE

Column Name Data Type Nullable?

EMPLOYEE_ID NUMBER NOT NULL
EMPLOYEE_NAME VARCHAR2 (40)
EMPLOYEE_HIRE_DATE DATE
EMPLOYEE_TERMINATION_DATE DATE
EMPLOYEE_BILLING_RATE NUMBER

DEFAULT VALUES FOR JEFF.EMPLOYEE

Column Name Default Value

EMPLOYEE_HIRE_DATE sysdate
The following example shows how you can look at the column definitions for a table owned by another user, in this
case the SYS user:

SQL> @list_columns sys.dual

COLUMN LISTING FOR SYS.DUAL

Column Name Data Type Nullable?

DUMMY VARCHAR2 (1)
Table Constraints
Information about constraints can be obtained from two data dictionary views: ALL_CONSTRAINTS and
ALL_CONS_COLUMNS. ALL_CONSTRAINTS returns one row for each constraint, and is the only view you need to
look at for the definition of a check constraint. Foreign key, primary key, and unique constraints are defined on one or
more columns, so for these there is a one-to-many relationship between ALL_CONSTRAINTS and
ALL_CONS_COLUMNS. Foreign keys are the most complicated, because to get a complete picture of a foreign key
constraint, you need to join the ALL_CONS_COLUMNS table to itself, then refer back to the ALL_CONSTRAINTS
view again. The reason for this is that a foreign key may be attached to either a primary key constraint or a unique
constraint. It's important to know which of the columns in the parent table matter.
Different Constraint Types Need Different Queries
There are four different types of constraints that can be created on a table. The four types are:
CHECK
PRIMARY KEY

< previous page page_200 next page >
< previous page page_201 next page >
Page 201
UNIQUE
FOREIGN KEY
These types are different enough that, with the exception of the PRIMARY KEY and UNIQUE constraints, you need a
slightly different query for each in order to see the definition.
CHECK constraints
A check constraint is simply an expression that must be true for each row in a table. This is the simplest of the

constraint types when it comes to querying the data dictionary tables. The check expression is stored in the
SEARCH_CONDITION column of the ALL_CONSTRAINTS table. The following query will get you the definition of
all CHECK constraints on a particular table:
SELECT constraint_name, search_condition
FROM all_constraints
WHERE owner = username
AND table_name = table_name
AND constraint_type = C
As you can see, the query is very simple. You don't even have to join any tables. With the other constraint types, the
query gets more complex.
PRIMARY KEY and UNIQUE constraints
Primary key and unique constraints are similar in that they both force each row in a table to have a unique value in one
column or combination of columns. The only difference between the two is semantics. When looking at constraints of
these two types, you need to include the ALL_CONS_COLUMNS view in your query in order to get a list of the
columns involved. The following query shows how to do this:
SELECT ac.constraint_name, ac.constraint_type,
ac.table_name, acc.column_name
FROM all_constraints ac,
all_cons_columns acc
WHERE ac.owner = username
AND ac.table_name = table_name
AND ac.constraint_type in (P,U)
AND ac.constraint_name = acc.constraint_name
AND ac.owner = acc.owner
ORDER BY ac.constraint_name, acc.position
Ordering the columns in the constraint definition by the POSITION column is done so the output matches the column
order used when originally defining a constraint. Oracle enforces unique and primary key constraints by creating unique
indexes. The column order used when creating the indexes will match that used in defining the constraints, and can
affect the performance of queries issued against the table.


< previous page page_201 next page >
< previous page page_202 next page >
Page 202
Foreign Key constraints
Foreign key constraints are the most complex. A foreign key defines a list of columns in one table, called the child
table, that correlates to either a primary key or a unique constraint on a parent table. When a row is inserted into the
child table, Oracle checks to be sure a corresponding parent record exists. Foreign key constraints involve two lists of
columns, one in the child table on which the constraint is defined, and another in the parent table.
The trick with foreign key constraints is to first find the name of the parent table, then find the names of the columns in
the parent table that correspond to the columns in the child table. The key to doing this is to use the R_OWNER and
R_CONSTRAINT_NAME columns in the ALL_CONSTRAINTS table. The constraint type code for foreign key
constraints is R. A foreign key always relates to either a primary key constraint or a unique constraint on the parent
table. The name of this related constraint will be in the R_CONSTRAINT_NAME column. Usually, the R_OWNER
column will match the OWNER column, but that doesn't have to be the case.
To see the definition of all the foreign key constraints for a given table, you can start with the query used for primary
key constraints, and modify it to look only at constraint type R:
SELECT ac.constraint_name, ac.constraint_type,
ac.owner, ac.table_name, acc.column_name
FROM all_constraints ac,
all_cons_columns acc
WHERE ac.owner = username
AND ac.table_name = table_name
AND ac.constraint_type = R
AND ac.constraint_name = acc.constraint_name
AND ac.owner = acc.owner
ORDER BY ac.constraint_name, acc.position
This will give you the constraint name, the table name, and a list of column names. It won't tell you the name of the
parent table or the names of the corresponding columns in that table. For that, you need to join ALL_CONSTRAINTS
to itself via the R_CONSTRAINT_NAME and R_OWNER columns. This will give you access to the parent table's
name.

SELECT ac.constraint_name, ac.constraint_type,
ac.owner, ac.table_name, acc.column_name,
r_ac.owner, r_ac.table_name
FROM all_constraints ac,
all_cons_columns acc,
all_constraints r_ac
WHERE ac.owner = username
AND ac.table_name = table_name
AND ac.constraint_type = R

< previous page page_202 next page >
< previous page page_203 next page >
Page 203
AND ac.constraint_name = acc.constraint_name
AND ac.owner = acc.owner
AND ac.r_owner = r_ac.owner
AND ac.r_constraint_name = r_ac. constraint_name
ORDER BY ac.constraint_Name, acc.position
Since most foreign key constraints relate to the parent table's primary key, you may want to just stop here. However,
since it is possible to relate a foreign key to a unique key on the parent table, you may want see the corresponding list of
parent table columns in order to fully understand the constraint. To do this, you must join with
ALL_CONS_COLUMNS once again and pick up the columns that go with the related parent table constraint. For
example:
SELECT ac.constraint_name, ac.constraint_type,
ac.owner, ac.table_name, acc.column_name,
r_ac.owner, r_ac.table_name,r_acc.column_name
FROM all_constraints ac,
all_cons_columns acc,
all_constraints r_ac,
all_cons_columns r_acc

WHERE ac.owner = username
AND ac. table_name = table_name
AND ac.constraint_type = R
AND ac.owner = acc.owner
AND ac.constraint_name = acc.constraint_name
AND ac.r_owner = r_ac.owner
AND ac.r_constraint_name = r_ac.constraint_name
AND r_ac.owner = r_acc.owner
AND r_ac.constraint_name = r_acc.constraint_name
AND acc.position = r_acc.position
ORDER BY ac.constraint_name, acc.position
Notice that the ALL_CONS_COLUMN table's POSITION column forms part of the join criteria. This ensures that
matching columns are output together, on the same line. You will see how this works in the next section, which presents
a script that will list all constraints defined for a table.
Listing the Constraints for a Table
With the three queries shown in the previous section, you have a good start on a script to show all constraints defined on
a table. Start by putting the three queries in a script, then qualify each with a table name. Use a substitution variable for
the table name so you can pass it to the script as a parameter. Next, format the results with some combination of the
COLUMN, BREAK, and TTITLE commands. The LIST_CONSTRAINTS script, shown next, shows one possible
approach you can take.

< previous page page_203 next page >
< previous page page_204 next page >
Page 204
The LIST_CONSTRAINTS.SQL script
DESCRIPTION
List all the constraints on a table.

INPUTS
Param 1 A table name, optionally qualified

by an owner name.
For example: SYS.ALL_TAB_COLUMNS.

SET ECHO OFF
SET NEWPAGE 1
SET VERIFY OFF
SET FEEDBACK OFF
SET HEADING OFF
SET PAGESIZE 9999
SET RECSEP OFF
SET CONCAT ON
CLEAR BREAKS
CLEAR COMPUTES
CLEAR COLUMNS
TTITLE OFF
BTITLE OFF

Dissect the input argument, and get the owner name and
table name into two seperate substitution variables.
The owner name defaults to the current user.
DEFINE s_owner_name =
DEFINE s_table_name =
COLUMN owner_name NOPRINT NEW_VALUE s_owner_name
COLUMN table_name NOPRINT NEW_VALUE s_table_name
SELECT
DECODE(INSTR(&&1, .),
0,USER, /*Default to current user.*/
UPPER(SUBSTR(&&1,1,INSTR(&&1,.)-1))) owner_name,
DECODE(INSTR(&&1,.),
0,UPPER(&&1), /*Only the table name was passed in.*/

UPPER(SUBSTR(&&1, INSTR(&&1,.)+1))) table_name
FROM dual;

Clear column definitions so that no future queries
affect the substitution variables that were just set.
CLEAR COLUMNS

Format the columns
COLUMN constraint_name NOPRINT NEW_VALUE constraint_name_var
COLUMN constraint_type_desc NOPRINT NEW_VALUE constraint_type_var
COLUMN r_owner NOPRINT NEW_VALUE r_owner_var
COLUMN r_table_name NOPRINT NEW_VALUE r_table_name_var
COLUMN status NOPRINT NEW_VALUE status_var
COLUMN delete_rule_desc NOPRINT NEW_VALUE delete_rule_var
COLUMN search_condition FORMAT A50 WORD_WRAPPED
COLUMN column_name FORMAT A30
COLUMN r_column_name FORMAT A30

< previous page page_204 next page >
< previous page page_205 next page >
Page 205
This script breaks on each constraint, and each constraint
has its own page title. The page title shows information
relating to the constraint as a whole.
BREAK ON constraint_name SKIP PAGE

Tell the user he is going to see constraints.
PROMPT CONSTRAINTS ON TABLE &&s_owner_name &&s_table_name

First show the primary key and unique constraints.


Set up the page title.
TTITLE LEFT constraint_name_var constraint_type_var
status_var SKIP 1

Run the query to display primary key and unique constraints.
SELECT ac.constraint_name,
DECODE(ac.constraint_type,
P, PRIMARY KEY,U,UNIQUE) constraint_type_desc,
table_name,
indent,
acc.column_name,
ac.status
FROM all_constraints ac,
all_cons_columns acc
WHERE ac.owner=&&s_owner_name
AND ac.table_name = &&s_table_name
AND ac.owner =acc.owner
AND ac.constraint_name = acc.constraint_name
AND ac.constraint_type IN (P, U,)
ORDER BY DECODE(ac.constraint_type, P,1,U,2),
ac.constraint_name,
acc.position;

Then show the foreign key constraints

Set up the page title for the foreign key constraints
TTITLE LEFT constraint_name_var status_var SKIP 1 -

FOREIGN KEY TO r_owner_var . r_table_name_var SKIP 1

Run the query to show foreign key constraints
SELECT ac.constraint_name,
indent,
acc.column_name,
r_acc.owner r_owner,
r_acc.table_name r_table_name,
r_acc.column_name r_column_name
FROM all_constraints ac,
all_cons_columns acc,
all_cons_columns r_acc
WHERE ac.owner=&&s_owner_name
and ac.table_name = &&s_table_name
AND ac.constraint_type = R
AND ac.owner = acc.owner

< previous page page_205 next page >
< previous page page_206 next page >
Page 206
AND ac.constraint_name = acc.constraint_name
AND ac.r_owner = r_acc.owner
AND ac.r_constraint_name = r_acc.constraint_name
AND acc.position = r_acc.position
ORDER BY ac.constraint_name, acc.position;

Then show the check constraints


Set up the page title for the check constraints
TTITLE LEFT constraint_name_var CHECK status_var SKIP 1


SELECT ac.constraint_name,
indent,
search_condition
FROM all_constraints ac
WHERE ac.owner = &&s_owner_name
AND ac.table_name = &&s_table_name
AND ac.constraint_type = C;

Undefine variables and restore settings to their defaults.
UNDEFINE s_owner_name
UNDEFINE s_table_name

SET NEWPAGE 1
SET VERIFY ON
SET FEEDBACK ON
SET HEADING ON
SET PAGESIZE 14
SET RECSEP WRAPPED
CLEAR BREAKS
CLEAR COMPUTES
CLEAR COLUMNS
TTITLE OFF
Running the LIST_CONSTRAINTS script
You can show all the constraints on a table by invoking the LIST_CONSTRAINTS script and providing the table name
as the first argument. The following example shows the constraints defined on the PROJECT_HOURS table:
SQL> @list_constraints project_hours

CONSTRAINTS ON TABLE JEFF.PROJECT_HOURS

PROJECT_HOURS_PK PRIMARY KEY ENABLED

PROJECT_ID
EMPLOYEE_ID
TIME_LOG_DATE

PROJECT_HOURS_UNIQUE UNIQUE ENABLED
PROJECT_ID
EMPLOYEE_ID
TIME_LOG_DATE
HOURS_LOGGED
DOLLARS_CHARGE

×