1. Trang chủ
  2. » Công Nghệ Thông Tin

Oracle SQL Plus The Definitive Guide- P27 docx

10 283 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 102,3 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Here's an example: SQL> PRINT my_string MY_STRING --- Brighten the corner where you are The bind variable is treated like a database column, with the variable name being the default colu

Trang 1

Is the name of the bind variable you want to print If you omit a name, the values of all bind variables are printed The results from the PRINT command look very much like the results you get from a SELECT Here's an example:

SQL> PRINT my_string

MY_STRING

-

Brighten the corner where you are

The bind variable is treated like a database column, with the variable name being the default column heading If you have page titles defined, they will print as well You can even use the COLUMN commands to format the output The following example shows how this works:

SQL> COLUMN my_string FORMAT A40 HEADING My Motto

SQL> PRINT my_string

My Motto

-

Brighten the corner where you are

SQL>

SQL> TTITLE LEFT This is a Page Title SKIP 2

SQL> COLUMN my_number FORMAT 99.99 HEADING My Age

SQL> PRINT my_number

This is a Page Title

My Age

-

36.00

All other formatting options, such as PAGESIZE and LINESIZE, apply when printing bind variables You can even use the COLUMN command's NEW_VALUE clause to store the value of a bind variable in a substitution variable, as the following example demonstrates:

SQL> DEFINE s_my_string =

SQL> COLUMN my_string NOPRINT NEW_VALUE s_my_string

SQL> PRINT my_string

SQL> PROMPT &&s_my_string

Brighten the corner where you are

Issuing the PRINT command by itself causes the contents of all bind variables to be displayed Here's an example:

SQL> PRINT

My Motto

-

Trang 2

Brighten the corner where you are

My Age

-

36.00

Some special considerations apply when printing bind variables of type CLOB and of type REFCURSOR These are described in the following sections.

Printing CLOB variables

The CLOB datatype is new with Oracle8 CLOB stands for character large object, and variables of this type can hold up to 2 gigabytes of text data When printing variables of type CLOB or NCLOB, there are three SQL*Plus settings you can use to control what you see and how that works See Table 7-2.

Table 7-2 Settings That Affect the Printing of CLOBs

setting Default Description

SET LONG 80 Controls the number of characters that are actually displayed from CLOB variable By

default, only the first 80 characters will print The rest are ignored.

SET LONGCHUNKSIZE 80 CLOB variables are retrieved from the database a piece at a time This setting controls

the size of that piece.

SET LOBOFFSET 1 An offset you can use to start printing with the nth character in the CLOB variable Be

default, SQL*Plus will begin printing with the first character A LOBOFFSET of 80, for example, skips the first 79 characters of the string.

By default, SQL*Plus will only display the first 80 characters of a CLOB value This is rarely enough After all, if you only needed 80 characters, you wouldn't have used a CLOB datatype in the first place On the other hand, you may not want to risk printing 2 gigabytes of data either.

The following example shows the result of printing a CLOB value using the default settings for the values in Table 7-2:

SQL> SELECT clob_value FROM clob_example;

CLOB_VALUE

-

By default, SQL*Plus will only display the first 80 characters of a CLOB value

1 row selected.

Trang 3

As you can see, only 80 characters of the value were displayed You can change the LONG setting to see more of the value, as the next example shows:

SQL> SET LONG 500

SQL> SELECT clob_value from clob_example;

CLOB_VALUE

-

By default, SQL*Plus will only display the first 80 characters of a CLOB

value This is rarely enough After all, if you only needed 80 characters,

you wouldn't have used a CLOB datatype in the first place

On the other hand, you may not want to risk printing 2 gigabytes of data either

1 row selected.

By combining the LOBOFFSET and LONG settings, you can print any arbitrary substring of a CLOB variable The following

example prints the characters 81 through 102, which make up the second sentence in the example:

SQL> SET LONG 22

SQL> SET LOBOFFSET 81

SQL> SELECT clob_value FROM clob_example;

CLOB_VALUE

-

This is rarely enough

1 row selected.

Finally, the LONGCHUNKSIZE setting controls the amount of the CLOB that is fetched from the database at one time If you have the memory available, you may want to set this to match the LONG setting That way SQL*Plus will retrieve the value with one fetch from the database, possibly improving performance.

Printing REFCURSOR variables

Beginning with Oracle8, SQLlus allows you to create bind variables of the type REFCURSOR A REFCURSOR variable is a pointer

to a cursor that returns a result set Using PL/SQL, you can assign any SELECT query to a variable of this type, and then you can use the SQL*Plus PRINT command to format and display the results of that query The following script makes use of this capability It asks the user for a pattern match string and prints the list tables with names that match the pattern supplied by the user A PL/SQL block is used to interpret the user's response, and to open a cursor that will return the desired results.

Find out what tables the user wants to see

A null response results in seeing all the tables

ACCEPT s_table_like PROMPT List tables LIKE >

VARIABLE l_table_list REFCURSOR

Trang 4

This PL/SQL block sets the l_table_list variable

to the correct query, depending on whether or

not the user specified all or part of a table_name

BEGIN

IF &&s_table_like IS NULL THEN

OPEN :l_table_list FOR

SELECT table_name

FROM user_tables;

ELSE

OPEN :l_table_list FOR

SELECT table_name

FROM user_tables

WHERE table_name LIKE UPPER (&&s_table_like);

END IF;

END;

/

Print the list of tables the user wants to see

PRINT l_table_list

As you can see, this script defines a SQL*Plus REFCURSOR variable The cursor is opened and a query assigned by code within a PL/SQL block Then the SQL*Plus PRINT command is used to display the results of that query

SQL> @ref_cursor

List tables LIKE >

TABLE_NAME

-

EMPLOYEE

PROJECT

PROJECT_HOURS

SQL>

SQL>

SQL> @ref_cursor

List tables LIKE > p%

TABLE_NAME

-

PROJECT

PROJECT_HOURS

The output you get when PRINTing a REFCURSOR variable is identical to the output you would get if you executed the same query directly from SQL*Plus

SELECTing a bind variable

The SQL*Plus manual, at least the one for versions 8.0.3 and before, will tell you that bind variables cannot be used in SQL statements Don't believe it Bind variables can be used in SELECT statements, both in the column list and in the WHERE clause You will frequently see this done in scripts where there is a need to get the contents of a bind variable into a substitution variable See the section

Trang 5

titled From bind to substitution earlier in this chapter Here's an example of a SELECT statement being used to display the contents of a bind variable:

SQL> VARIABLE l_user VARCHAR2(30)

SQL> EXECUTE ;l_user := user;

SQL> SELECT :l_user FROM dual;

:L_USER

-

NATHAN

Using SELECT like this offers no real advantage over the use of the PRINT command If you just need to display one variable, you might as well PRINT it Being able to use bind variables in a SELECT statement becomes more of an advantage when you need to display information from more than one column, when you want to use the bind variable in

an expression for a computed column, or when you want to use it in the WHERE clause Here's an example that

combines all three of these:

SQL> SET HEADING OFF

SQL> SELECT User ¦¦ :l_user ¦ ¦ has

2 ¦ ¦ TO_CHAR(COUNT(*)) ¦ ¦ tables

3 FROM all_tables

4 WHERE owner = :l_user;

NATHAN

User SQLPLUS has 3 tables

Two types of bind variables cannot be used in a SQL statement These are the REFCURSOR and CLOB types You must use the PRINT command with these

When and How to Use Bind Variables

There are three primary reasons to use bind variables in SQL*Plus:

You need to call PL/SQL procedures or functions that return a value or that use IN OUT parameters

You need to conditionally execute one of several possible SELECT statements depending on user input or other

circumstances

You want to test a query for use in an application, and that query uses colons to mark parameters

The next few sections briefly describe each of these uses

Calling PL/SQL procedures and functions from SQL*Plus

Oracle provides a number of built-in PL/SQL packages that allow you to do such things as create and execute dynamic SQL queries (the DBMS_QL package), submit and manage PL/SQL batch jobs (the DBMS_JOBS package), and many other very useful things In many cases, the procedures and functions in these packages

Trang 6

use OUT parameters to return information to the caller To call these routines from within a SQL*Plus script and

display the results to the person running the script, you need to use bind variables

Consider the problem of writing a SQL*Plus script to submit a PL/SQL job for periodic execution by Oracle To do this, you would use a procedure in Oracle's DBMS_JOBS package named SUBMIT SUBMIT takes several arguments, one of which is an OUT argument The declaration for SUBMIT looks like this:

DBMS_JOB SUBMIT( job OUT BINARY_INTEGER,

what IN VARCHAR2,

next_date IN DATE DEFAULT SYSDATE,

interval IN VARCHAR2 DEFAULT null,

no_parse IN BOOLEAN DEFAULT FALSE)

The job parameter is the job number, and is an output from the procedure This job number uniquely identifies a job within Oracle, and is important to know because all the procedures to modify, delete, or otherwise manage database jobs require the job number as an input Here is one approach you could use to write a script that submits a PL/SQL job for a user In particular, note the use of a bind variable in the EXECUTE command Also note the subsequent PRINT

command that displays the job number to the user

SET ECHO OFF

SET FEEDBACK OFF

SET VERIFY ON

SET HEADING ON

SET TERMOUT ON

This script submits a job to the queue after first

prompting the user for the required information

Get the neccessary information from the user

PROMPT

prompt Submit a PL/SQL job

PROMPT

ACCEPT what CHAR PROMPT Enter the PL/SQL statement to execute >

PROMPT

ACCEPT when CHAR PROMPT When (e.g 15-Nov-1961 18:30)?

ACCEPT interval CHAR PROMPT Interval (e.g sysdate+1)?

Submit the job

VARIABLE job_number NUMBER

EXECUTE DBMS_JOB.SUBMIT(:job_number, &what, &when, &interval);

Tell the user the job's ID number

PRINT job_number

SET FEEDBACK ON

SET VERIFY ON

Trang 7

Running the above script looks like this:

SQL> @submit_job

Submit a PL/SQL job

Enter the PL/SQL statement to execute >NULL;

When (e.g 15-Nov-1961 18:30)?sysdate

Interval (e.g sysdate+1)?sysdate+1

JOB_NUMBER

-

4

NULL is a valid PL/SQL statement that does nothing, and is often used as a place-holder for code to be written later In this example, Oracle will do nothing once each day

Using REFCURSOR variables

As mentioned earlier, the REFCURSOR datatype holds a pointer to a cursor, and is a new feature introduced with

Oracle8 Using REFCURSOR variables, you can open a cursor for a SELECT statement in PL/SQL and print the results from SQL*Plus One practical use for this is to write PL/SQL code that selects one query from many possibilities, based

on user input or some other factor

Earlier, in the section on printing, you saw a REFCURSOR example that printed a list of tables owned by the current user Here is an enhanced version of that script that allows the user to optionally enter a pattern match string to narrow the list of table names to be displayed The script executes one of two possible queries depending on whether or not a string was supplied

Find out what tables the user wants to see

A null response results in seeing all the tables

ACCEPT s_table_like PROMPT List tables LIKE >

VARIABLE l_table_list REFCORSOR

This PL/SQL block sets the l_table_list variable

to the correct query, depending on whether or

not the user specified all or part of a table_name

BEGIN

IF &&s_table_like IS NULL THEN

OPEN : l_table_list FOR

SELECT table_name

FROM user_tables;

ELSE

OPEN :l_table_list FOR

SELECT table_name

FROM user_tables

WHERE table_name LIKE UPPER(&&s_table_like);

Trang 8

END IF;

END;

/

Print the list of tables the user wants to see

PRINT l_table_list

This script first asks the user for a search string to be used with the LIKE operator Entering this is optional If a pattern match string is specified, then only table names that match that string are displayed; otherwise, all table names are listed This conditional logic is implemented by the PL/SQL block, which checks the value of the substitution variable and then opens the REFCURSOR variable using the appropriate SELECT statement Here's how it looks to run the script:

SQL> @ref_cursor

List tables LIKE >

TABLE_NAME

-

EMPLOYEE

PROJECT

PROJECT_HOURS

SQL>

SQL>

SQL> @ref_cursor

List tables LIKE > p%

TABLE_NAME

-

PROJECT

PROJECT_HOURS

You can see that when no search string was specified, all the tables were listed, whereas entering a search string of p% caused only tables starting with the letter P to be listed The output is just like that from a standard SELECT statement, and all the column and page formatting options of SQL*Plus apply

You might be thinking now about using REFCURSOR variables with the DBMS_SQL package to return the results of dynamically generated SQL queries back to

SQL*Plus Unfortunately, that can't be done DBMS_SQL returns integer values that

reference cursors held internally, but there is no way to get a REFCURSOR value pointing to

one of those cursors

Using REFCURSOR variables is one way to add conditional logic to your SQL*Plus scripts You'll see another

example of this later in the section titled Branching in SQL*Plus

Trang 9

Testing application queries

Bind variables can make it more convenient to take a query from an application development environment such as PowerBuilder and debug it using SQL*Plus PowerBuilder queries often contain parameters to be supplied at runtime PowerBuilder parameters are preceded by colons, the same syntax SQL*Plus uses for bind variables If you had a

PowerBuilder datawindow that allowed you to edit just one employee record, here is how the query behind that

datawindow might look:

SELECT employee.employee_id,

employee.employee_name,

employee.employee_hire_date,

employee.employee_termination_date,

employee.employee_billing_rate

FROM employee

WHERE employee.employee_id = :emp_id

Now if you want to test this query, and you just paste it into SQL*Plus as it is, you will get the following results:

SQL> SELECT employee employee_id,

2 employee.employee_name,

3 employee.employee_hire_date,

4 employee employee_termination_date,

5 employee.employee_billing_rate

6 FROM employee

7 WHERE employee employee_id = :emp_id

8 /

Bind variable EMP_ID not declared

At this point, you have two choices You can change the query and simply replace the parameter :emp_id with an

employee number that you know exists Then you can test the query, and when you are satisfied the query works, you can replace the hardcoded value with the parameter reference Woe be unto you, however, if there are several

parameters and you forget to change one back A safer approach would be simply to declare bind variables to match the parameters in the query In this case there's just one to declare:

SQL> VARIABLE emp_id NUMBER

Once the variable has been declared, it is a simple matter to initialize it to a known good value:

SQL> EXECUTE :emp_id := 101;

PL/SQL procedure successfully completed

Having declared and initialized the variable, it's now a simple matter to copy the query directly from PowerBuilder, or wherever, and paste it unchanged into SQL*Plus:

Trang 10

SQL> SELECT employee.employee_id,

2 employee.employee_name,

3 employee.employee_hire_date,

4 employee.employee_termination_date,

5 employee.employee_billing_rate

6 FROM employee

7 WHERE employee.employee_id = :emp_id

8 /

EMPLOYEE_ID EMPLOYEE_NAME EMPLOYEE_ EMPLOYEE_ EMPLOYEE_BILLING_RATE

- - - - -

101 Jonathan Gennick 15-NOV-61 169

Once you are satisfied that everything is correct, you can paste the query directly back into your application without the risk that you might forget to manually change a hardcoded value back into a parameter

Branching in SQL*Plus

SQL*Plus has no IF statement This is a very vexing thing Script writing is similar to programming It's natural to want to take different actions depending on user input or some other condition Imagine how frustrated you would be if your

favorite programming language suddenly lost its IF statement! Despite the lack of an IF statement in SQL*Plus, there are some approaches you can take to get equivalent results Some are more straightforward than others All involve some

compromises

Approaches to Branching

There are at least six approaches you can take to the problem of conditional execution These are:

Simulate branching by adjusting the WHERE clause in a query

Use REFCUSOR variables

Use a multilevel file structure

Use SQL to write SQL

Use PL/SQL for conditional logic

Use an operating-system scripting language

Some of these approaches are very specific to certain types of problems Using REFCURSOR variables, for example, is a good solution when you simply need to choose which query to run based on user input or some other condition Other approaches, such as the use of a multilevel file structure for your script, are more general in nature, and can be used for any type of branching

Ngày đăng: 05/07/2014, 04:20

TỪ KHÓA LIÊN QUAN