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

Oracle SQL Plus The Definitive Guide- P26 potx

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 (102.92 KB, 10 trang )

< previous page page_224 next page >
Page 224
The SHOW_SECURITY.SQL script
The following script shows you the grants that have been made on any table you own. You can also see grants made on
tables owned by other users, so long as those grants apply to you. The two queries you saw previously have been
unioned together, and the columns have been concatenated together to produce readable output. The table name and
grantee are shown in the header, which changes each time the grantee changes.
DESCRIPTION
This script displays information about security on a table.

USAGE
@SHOW_SECURITY [owner.] table_name

SET ECHO OFF
SET VERIFY OFF
SET FEEDBACK OFF
SET PAGESIZE 9999
SET HEADING OFF

Dissect the input argument, and get the owner name and
table name into two separate substitution variables.
The owner name defaults to the current user.
SET TERMOUT OFF
DEFINE s_owner_name =
DEFINE s_synonym_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,.),
UPPER(&&1), /*Only the table name was passed in.*/
UPPER(SUBSTR(&&1,INSTR(&&1,.)+1))) table_name
FROM dual;
SET TERMOUT ON

COLUMN grantee NOPRINT NEW_VALUE s_grantee
BREAK ON grantee SKIP PAGE
TTITLE LEFT PRIVILEGES GRANTED TO s_grantee -
ON s_owner_name . s_table_name

Execute a query to show privileges granted at the table level.
SELECT grantee,
¦¦ privilege ¦¦
DECODE(grantable, YES, with grant option, ) privilege
FROM all_tab_privs
WHERE table_schema = &&s_owner_name
AND table_name = &&s_table_name
UNION
SELECT grantee,

< previous page page_224 next page >
< previous page page_225 next page >
Page 225
¦¦ privilege ¦¦ of column ¦¦ column_name
¦¦ DECODE(grantable, YES, with grant option, ) privilege
FROM all_col_privs
WHERE table_schema = &&s_owner_name
AND table_name = &&s_table_name
ORDER BY grantee, privilege;


Reset everything back to its default.
CLEAR COLUMNS
CLEAR BREAK
UNDEFINE s_owner_name
UNDEFINE s_table_name
SET VERIFY ON
SET FEEDBACK ON
SET HEADING ON
SET PAGESIZE 24
Running the SHOW_SECURITY script
The following example shows the results of running SHOW_SECURITY against the EMPLOYEE table, after first
granting some access to other users:
SQL> @show_security employee

PRIVILEGES GRANTED TO PUBLIC ON JEFF.EMPLOYEE
SELECT
UPDATE of column EMPLOYEE_TERMINATION_DATE

PRIVILEGES GRANTED TO USER_A ON JEFF.EMPLOYEE
DELETE
INSERT of column EMPLOYEE_BILLING_RATE with grant option
INSERT of column EMPLOYEE_HIRE_DATE with grant option
INSERT of column EMPLOYEE_ID with grant option
INSERT of column EMPLOYEE_NAME with grant option
SELECT

PRIVILEGES GRANTED TO USER_B ON JEFF.EMPLOYEE
UPDATE of column EMPLOYEE_NAME
UPDATE of column EMPLOYEE_TERMINATION_DATE


PRIVILEGES GRANTED TO USER_C ON JEFF.EMPLOYEE
INSERT
INSERT of column EMPLOYEE_ID
SELECT
UPDATE
Finding More Information
It's well worth your time to learn more about Oracle's data dictionary views. Anything you want to know about the
structure of your database and the objects within it can be found by querying the appropriate view. The definitive
reference for these views is the Oracle8 Server Reference manual. However, if you don't

< previous page page_225 next page >
< previous page page_226 next page >
Page 226
have that manual close by, you can get a quick list of useful views by executing the following query:
SELECT *
FROM dictionary
ORDER By table_name;
Use the DESCRIBE command on any views of interest. The column names tend to be reasonably self-explanatory.

< previous page page_226 next page >
< previous page page_227 next page >
Page 227
7
Advanced Scripting
In this chapter
Bind Variables
Branching in SQL*Plus
Looping in SQL*Plus
Validating and Parsing User Input

Error Handling

SQL*Plus was not designed to be a tool used for writing complex scripts. Its capabilities cannot compare to those of
your typical Unix shell, such as the Kom shell or the Bourne shell. Nor does it have anywhere near the capabilities of an
advanced scripting tool such as Perl. Most noticeably, SQL*Plus suffers from the following limitations:
It lacks an IF statement.
There are no looping constructs.
It has very limited error handling.
There is only marginal support for validating user input.
Because of these limitations, SQL*Plus is best suited to executing top-down scripts that don't require any branching,
looping, or error handling. Most of the scripts you have seen so far in this book fall into this category. Many are reports
that simply set up some column and page formatting, then execute a query. If something goes wrong, you either don't
see any data in the report or may see some SQL or SQL*Plus error messages.
This limited scripting support is fine when it comes to producing a report. After all, if a report fails, you can simply fix
the problem and return the report. But what if you are performing a more complex and critical task? What if you are
summarizing some data, posting the summary results to a summary table, and then deleting the underlying detail? In
that case, you certainly wouldn't want to delete the data if the summarization failed. You would need some sort of error-
handling mechanism.

< previous page page_227 next page >
< previous page page_228 next page >
Page 228
If you need to write scripts of any significant complexity, I strongly encourage you
to investigate the use of PL/SQL in your script. PL/SQL is a powerful programming language
in its own right, and includes support for error handling, branching, and loopingthe very items
that SQL*Plus lacks. Steven Feuerstein's and Bill Pribyl's book, Oracle PL/SQL
Programming, 2nd edition (O'Reilly, 1997), is an excellent resource.
This chapter will show you some specific ways to work around these limitations of SQL*Plus. Believe it or not, it is
possible, using just SQL*Plus, to implement branching and to validate user input. There are even ways to deal with
repetitive tasks without resorting to a loop. You will learn about bind variables and see how they better enable you to

mix PL/SQL code into your SQL*Plus scripts. You will also see how bind variables can make the job of developing
queries for application programs a little bit easier.
Bind Variables
Back in Chapter 4, Writing SQL*Plus Scripts, you learned about substitution variables. In addition to substitution
variables, SQL*Plus supports another type of variable called a bind variable. Unlike substitution variables, bind
variables are real variables, having both a datatype and a size.
Bind variables were created to support the use of PL/SQL in a SQL*Plus script. They provide a mechanism for
returning data from a PL/SQL block back to SQLlus, where it can be used in subsequent queries or by other PL/SQL
blocks. Here's a simple example showing how a bind variable can be used:
Bind variables can be declared in your SQL*Plus script.
VARIABLE s_table_name varchar2(30)

Preface a bind variable with a colon to reference it
in a PL/SQL block.
BEGIN
:s_table_name := EMPLOYEE;
END;
/

Bind variables can even be referenced by SQL queries.
SELECT index_name
FROM user_indexes
WHERE table_name = :s_table_name;

Bind variables persist until you exit SQL*Plus, so
they can be referenced by more than one PL/SQL block.
SET SERVEROUTPUT ON

< previous page page_228 next page >
< previous page page_229 next page >

Page 229
BEGIN
DBMS_OUTPUT. PUT_LIKE(: s_table_name) ;
END;
/
The scope of a bind variable is the SQL*Plus session in which it was defined. Variables defined within a PL/SQL block,
on the other hand, cease to exist once that block has finished executing. Bind variables are defined one level higher (at
the SQL*Plus level), so they can be referenced by many PL/SQL blocks and queries.
Declaring Bind Variables
The SQLlus VARIABLE command is used to declare bind variables. The syntax looks like this:
VAR[IABLE] var_name data_type
where:
VAR[IABLE]
Is the command, which can be abbreviated to VAR.
var_name
Is whatever name you want to give the variable. A variable name must start with a letter, but after that, the name may
contain any combination of letters, digits, underscores, pound signs, and dollar signs. 30 characters is the maximum
length for a variable name.
data_type
Is the datatype of the variable. The following datatypes are allowed:
NUMBER
Results in a floating-point number, and is the same as a NUMBER variable in PL/SQL or a NUMBER column in a
table. Unlike PL/SQL, SQL*Plus does not let you specify a length or a precision, so a declaration like NUMBER
(9,2) would not be allowed.
CHAR[(length)]
Results in a fixed-length character string. Length is optional. If it's omitted, you get a one-character string.
NCHAR[(length)]
Results in a fixed-length character string in the national character set. Length is optional. If it's omitted, you get a
one-character string.
VARCHAR2(length)

Results in a variable-length character string.

< previous page page_229 next page >
< previous page page_230 next page >
Page 230
NVARCHAR2(length)
Results in a variable-length character string using the national language character set.
CLOB
Results in a character large object variable.
NCLOB
Results in a character large object variable using the national language character set.
REFCURSOR
Gives you a cursor variable that you can use to return the results of a SQL query from PL/SQL to SQL*Plus.
In addition to declaring variables, you can also use the VARIABLE command to list all the variables you have defined.
To do that, simply issue the command VARIABLE, with no arguments, as shown in the following example:
SQL>VARIABLE
variable jenny
datatype NUMBER

variable jeff
datatype CHAR

variable sharon
datatype VARCHAR2(30)
If you are interested in one specific variable, you can specify that variable's name as an argument to the VARIABLE
command, for example:
SQL> VARIABLE SHARON
variable sharon
datatype VARCHAR2(30)
There is no way to get rid of a variable once you've defined it.

Using Bind Variables and Substitution Variables Together
Bind variables and substitution variables don't mesh together too well in SQL*Plus. Each was created for a different
purpose, and the two types cannot be used interchangeably. For example, bind variables cannot be used with the
ACCEPT command, while substitution variables can. Substitution variables can be used with the TTITLE and BTITLE
commands that set up page headers and footers, while bind variables cannot. Bind variables are true variables, and can
be passed as argu-

< previous page page_230 next page >
< previous page page_231 next page >
Page 231
ments to PL/SQL functions and procedures, while substitution variables cannot. Table 7-1 summarizes the best uses and capabilities of
each type of variable.
Table 7-1. Bind Variables versus Substitution Variables
Task Bind Variable Substitution Variable Comments
Display information to the userthe
PROMPT command.
X
Accept input from the userthe ACCEPT
command.
X
Place information from a query into
page headers and footersthe TITTLE
and BTITLE commands.
X
Run a query with user-specified criteria
in the WHERE clause.
X X User input must come through a
substitution variable, but you can store
the resulting value in a bind variable.
Pass values to a PL/SQL function or

procedure.
X X Substitution variables may be used to
pass input arguments as literals.
Return information back from a PL/
SQL function or procedure.
X Bind variables must be used for OUT
and IN OUT arguments.

As you can see, each variable type pretty much exists in its own world, completely separate from the other. In fact, you cannot even
directly assign values from a bind variable to a substitution variable, or vice versa. The following lines of script, though appearing
perfectly reasonable on the surface, simply will not work:
DEFINE my_sub_var =
VARIABLE my_bind_var VARCHAR2(30)
EXECUTE :my_bind_var := Donna Gennick
my_sub_var = my_bind_var
This lack of interoperability between variable types can be a real frustration when writing scripts. As Table 7-1 shows, there are some
tasks for which you can only use a bind variable, and others for which you can only use a substitution variable. Yet SQL*Plus does not let
you easily move values back and forth between the two types. Fortunately, there are some relatively straightforward incantations that let
you work around this problem.
From substitution to bind
Putting the value of a substitution variable into a bind variable is actually the easier of the two tasks. Remember that as SQL*Plus
executes your script, any substitu-

< previous page page_231 next page >
< previous page page_232 next page >
Page 232
tion variables are simply replaced by their contents as each line of code is executed. You can easily take advantage of
this in order to place a value into a bind variable. Take a look at the following short script:
DEFINE my_sub_var = Raymond
VARIABLE my_bind_var VARCHAR2(30)

EXECUTE :my_bind_var := &my_sub_var;
EXECUTE is a command that executes one line of PL/SQL code. When SQL*Plus encounters the EXECUTE
command, it replaces the reference to the substitution variable with the value of that variable. The command after
substitution, the one that is actually executed, looks like this:
EXECUTE :my_bind_var := Raymond;
Since the assignment involves a character string, the substitution variable must be contained in quotes; otherwise, you
would not have a valid string. If you are working with numeric values, you shouldn't quote them. The following
example declares a variable of type NUMBER and assigns a value to it:
DEFINE imy_sub_num = 9
VARIABLE my_bind_num NUMBER
EXECUTE :my_bind_num := &&my_sub_num;
So quote your strings, don't quote your numbers, and remember that substitution is occurring.
From bind to substitution
Taking a value from a bind variable and placing it into a substitution variable is a more difficult task. What you need to
do is take advantage of SQL*Plus's ability to store the results of a SELECT statement into a substitution variable. Let's
say you have the following in your script:
DEFINE my_sub_var =
VARIABLE my_bind_var VARCHAR2(30)
EXECUTE :my_bind_var := This is a test.;
In order to get the value of the bind variable into the substitution variable, you need to go through the following steps:
1. Think up a column name.
2. Execute a COLUMN command for the column name you thought up. Use the NEW_VALUE clause and specify the
substitution variable as the target.
3. Turn off terminal output by executing a SET TERMOUT OFF command. This is optional.
4. Issue a SELECT statement that selects the bind variable from Oracle's DUAL table. Use the column name you
thought up in step 1 as the column alias.
5. Turn terminal output back on.

< previous page page_232 next page >
< previous page page_233 next page >

Page 233
The SELECT statement will, of course, only return one value, but that value will be a new value for the column in
question. The COLUMN command, with its NEW_VALUE clause, causes this value to be stored in the specified
substitution variable. It's a roundabout solution to the problem, but when it's all over the substitution variable will
contain the value from the bind variable. The important thing is to be sure that the column alias matches the column
name used in the COLUMN command. Here's a code sample that demonstrates this technique:
Declare one bind variable and one substitution variable.
Initialize the bind variable to a value.
DEFINE my_sub_var =
VARIABLE my_bind_var VARCHAR2(30)
EXECUTE :my_bind_var := This is a test.;

Store the new value of the my_alias column in my_sub_var.
COLUMN my_alias NEW_VALUE my_sub_var

SELECT the value of the bind variable. SQL*Plus
will store that value in my_sub_var because of the
previous COLUMN command.
SET TERMOUT OFF
SELECT :my_bind_var my_alias
FROM dual;
SET TERMOUT ON
Notice that a column alias is used in the SELECT statement to give the column a name. This same name must be used
in the COLUMN command issued prior to the SELECT. If these two don't match, then the assignment won't be made,
and my_sub_var will still be blank.
Strictly speaking, it's not necessary to turn the terminal output off for the SELECT statement. The variable assignment
will still be made, even with the output on. However, if you are writing a script, you probably won't want the results of
this SELECT to clutter up the display.
Displaying the Contents of a Bind Variable
There are two ways to display the contents of a bind variable to a user. You can use the PRINT command, or you can

list the variable in a SELECT statement.
The PRINT command
The format for the PRINT command looks like this:
PRI[NT] [bind_variable_name]
where:
PRI[NT]
Is the command, which can be abbreviated to PRI.

< previous page page_233 next page >

×