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

Oracle SQL Plus The Definitive Guide- P28 ppsx

10 232 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 121,51 KB

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

Nội dung

--DESCRIPTION --Print one of three user security reports SET FEEDBACK OFF SET PAGESIZE 20 SET LINESIZE 77 SET HEADING ON --Ask the user what report to print PROMPT PROMPT 1 - List users

Trang 1

Page 244

Simulating Branching by Adjusting the WHERE Clause.

Suppose you are writing a script to delete all data from the project_hours table Before you delete the data, you want to ask the user to confirm the operation You really want to write something like this:

ACCEPT s_delete_confirm PROMPT Delete project hours data (Y/N)?

IF s_delete_confirm = Y THEN

DELETE

FROM project_hours;

END IF

Of course, you can't do that! SQL*Plus has no IF statement, remember? However, you can add a WHERE clause to the DELETE statement that will have the same effect Here's an example:

SET VERIFY OFF

ACCEPT s_delete_confirm PROMPT Delete project hours data (Y/N)?

DELETE

FROM project_hours

WHERE UPPER(&&s_delete_confirm) = Y;

When you execute the script, the DELETE will always be executed However, if the user answers with an N, the

WHERE clause will always evaluate to FALSE, and no rows will be deleted Verification is set off only to prevent SQL*Plus from echoing the line of the WHERE clause that references the substitution variable The UPPER function is used in this case in order to allow the user's response to be case-insensitive Here's how it looks when a user runs this script and doesn't confirm the delete:

SQL> @delete_hours

Delete project hours data (Y/N)?n

0 rows deleted

If you wanted to, you could even write an additional query to give the user an error message if the response to the

prompt was not a Y or an N Adding these lines immediately after the ACCEPT statement would do that for you:

SET HEADING OFF

SET PAGESIZE 0

SET FEEDBACK OFF

SELECT You must answer with a Y or N

FROM DUAL

WHERE UPPER(&&s_delete_confirm) NOT IN (y,N)

OR &&s_delete_confirm IS NULL;

Trang 2

SET FEEDBACK ON

SET PAGESIZE1

SET HEADING ON

To make the results of this query look like an error message, both headings and pagination are turned off Feedback is also turned off to avoid giving the 1 row selected message to the user After the SELECT executes, these settings are returned to their defaults Now, here is what happens when you run the modified script and don't answer with a Y or N:

SQL> @delete_hours

Delete project hours data (Y/N) ?X

You must answer with a Y or N

0 rows deleted

This technique has the advantage of keeping your entire script in one file, but it's pretty much limited to handling the case where you have several possible queries to execute and must choose the correct one based on input from the user

Using REFCURSOR Variables to Simulate Branching

If you want to present the user with a choice of reports to run, you can place the conditional logic within PL/SQL and use a REFCURSOR variable to return the selected query to SQL*Plus, where the results can be formatted and printed

REFCURSOR variables are only available beginning with SQL*Plus version 8 and above

The following script gives the user a choice of three different reports The conditional logic is implemented in a PL/ SQL block, and the results are returned to SQL*Plus via bind variables A REFCURSOR bind variable is used to return

a query that generates the report requested by the user

DESCRIPTION

Print one of three user security reports

SET FEEDBACK OFF

SET PAGESIZE 20

SET LINESIZE 77

SET HEADING ON

Ask the user what report to print

PROMPT

PROMPT 1 - List users

PROMPT 2 - List users and table privileges

PROMPT 3 - List users and system privileges

Trang 3

Page 246 PROMPT

ACCEPT s_report_choice PROMPT Enter your choice (1,2,3) >

A PL/SQL block will set the b_report bind variable

to a query based on the user's response Text for the

report title will be returned in b_report_type

VARIABLE b_report REFCURSOR

VARIABLE b_report_type VARCHAR2 (30)

Interpret the user's choice

BEGIN

IF &&s_report_choice = 1 THEN

Return some text for the title to identify this report

:b_report_type := User Listing;

Return a query that will list all users

OPEN :b_report FOR

SELECT username

FROM dba_users

ORDER BY username;

ELSIF &&s_report_choice = 2 THEN

Return some text for the title to identify this report

:b_report_type := User Table Privileges;

Return a query that will list users and any

privileges they have on tables in the database

OPEN :b_report FOR

SELECT username, privilege, owner, table_name

FROM dba_users, dba_tab_privs

WHERE username = grantee

ORDER BY username, owner, table_name, privilege;

ELSIF &&s_report_choice = 3 THEN

Return some text for the title to identify this report

:b_report_type := User System Privileges;

Return a query that lists users and any system

privileges they have been granted

OPEN :b_report FOR

SELECT username, privilege

FROM dba_users, dba_sys_privs

WHERE username = grantee

ORDER BY username, privilege;

ELSE

Return some text for the title to identify this report

:b_report_type := Invalid Report Choice;

The user made an invalid choice, so

return a query that will display an error message

OPEN :b_report FOR

SELECT You must choose either 1, 2, or 3 error_message

FROM dual;

END IF;

Trang 5

Page 247

Specify formats for all possible report columns.COLUMN

username FORMAT A12 HEADING User

COLUMN privilege FORMAT A20 HEADING Privilege

COLUMN owner FORMAT A12 HEADING Table Owner

COLUMN table_name FORMAT A30 HEADING Table Name

COLUMN error_message FORMAT A40 HEADING Error Message

Set up the page title First we have to get the contents of

b_report_type into a substition variable

set termout off

COLUMN b_report_type FORMAT A30 NOPRINT NEW_VALuE s_report_type

SELECT b_report_type FROM dual;

set termout on

TTITLE LEFT s_report_type RIGHT Page FORMAT 999 SQL.PNO SKIP 2

Run the report requested by the user

PRINT b_report

Note that the script contains COLUMN commands for all possible columns from the three different queries These don't need to

be conditionally executed, because format definitions for columns not used in the final query are ignored by SQL8Plus Also note that the PL/SQL code does return a query even for the case where the user's input is invalid; this query simply selects an error message from the DUAL table Here is the output from running this script, first showing the results of an invalid input, then showing the output from one of the reports:

SQL> @user_security

1 - List users

2 - List users and table privileges

3 - List users and system privileges

Enter your choice (1,2,3) >4

User Listing Page 1

Error Message

-

You must choose either 1, 2, or 3

SQL> @user_security

1 - List users

2 - List users and table privileges

3 - List users and system privileges

Enter your choice (1,2,3) >2

User Listing Page 1

Trang 6

User Privilege Table Owner Table Name

- - - -

SYSTEM EXECUTE SYS AQS_AGENT

SYSTEM EXECUTE SYS AQS_DEQUEUE_HISTORY

SYSTEM EXECUTE SYS AQS_HISTORY

SYSTEM EXECUTE SYS AQS_RECIPIENTS

SYSTEM EXECUTE SYS AQS_SUBSCRIBERS

SYSTEM EXECUTE SYS DBMS_ADAM

SYSTEM EXECUTE SYS DBMS_AQ_IMPORT_INTERVAL

SYSTEM EXECUTE SYS DBMS_DEFER_IMPORT_INTERVAL

SYSTEM ALTER SYS INCEXP

SYSTEM DELETE SYS INCEXP

SYSTEM INDEX SYS INCEXP

In this example, the query output is only displayed on the screen If you wanted to print it, you would just need to add a SPOOL command to send the output to a file, which you could later send to a printer.

Branching Using a Multilevel File Structure

The most generic and flexible approach to branching that you can implement using SQL*Plus is to write your script to execute one of several alternative files based on user input or other criteria This is best explained by example, so here is a simplified version of the security reports menu shown previously in this chapter:

Ask the user what report to print

PROMPT

PROMPT 1 - List users

PROMPT 2 - List users and table privileges

PROMPT 3 - List users and system privileges

PROMPT

ACCEPT s_report_choice PROMPT Enter your choice (1,2,3) >

Execute the appropriate report

@user_security_&&s_report_choice

The key to this approach is in the last line, where the user's response is used to form the name of another SQL file to execute If the user chooses option 1, for example, the last line in the above script will be translated to:

@user_security_1

Of course, you have to make sure that a file named USER_SECURITY_1 SQL exists and that it will generate the correct report

When you use this approach to branching, you will end up with a set of script files that form an inverted tree structure The tree diagram in Figure 7-1 shows the relationship between the menu script and the scripts that run the individual reports.

Because this branching technique executes another SQL*Plus script, you can continue to ask the user questions, and even branch again depending on the user's response The one thing you have to watch out for is that SQL*Plus cannot nest

Trang 7

Page 249

Figure 7-1 Structure for the security reports menu, using a multilevel file structure scripts indefinitely SQL*Plus can currently nest scripts only 20 levels deep, and some older versions only allow 5 levels of nesting

A useful variation on this technique is to code it using a SELECT statement to analyze the user's input and derive the name of the next script to call You get two benefits from this: the script names are not directly linked to the user's input, and it's easier to designate one script to be called when the user makes an invalid choice The only penalty is a small amount of added complexity in your script The following script is an example of this technique:

Ask the user what report to print

PROMPT

PROMPT A - List users

PROMPT B - List users and table privileges

PROMPT C - List users and system privileges

PROMPT

ACCEPT s_report_choice PROMPT Enter your choice (A,B,C) >

DECODE the user's input

SET TERMOUT OFF

COLUMN user_choice NOPRINT NEwVALUE s_next_script

SELECT DECODE (UPPER ( &s_report_choice) ,

A,USER_SECURITY_1.SQL,

B,USER_SECURITY_2.SQL,

C,USER_SECURITY_3>SQL,

USER_SECURITY_ $.SQL)user_choice

FROM DUAL;

SET TERMOUT ON

Execute the appropriate report

@@&s_next_script

The key to this script is the call to DECODE in the SELECT statement DECODE is a SQL function that allows you to

Trang 9

Page 250 the UPPER function, we allow the user to respond in either uppercase or lowercase Following the input are three value pairs, each specifying the output for a specific input value An input of A causes this DECODE to return

USER_SECURITY_1.SQL, an input of B causes USER_SECURITY_2.SQL to be returned, and so forth The final value, USER_SECURITY_4.SQL, is returned if the user's choice did not match any of the others In this case, the file

USER_SECURITY_4.SQL would display some sort of error message, telling the user what he did wrong.

If you decide to develop a set of scripts like this, it's best to spend some time up front working out the structure before you begin scripting Making changes after you've started writing a set of scripts like this can become cumbersome very quickly because so many files are involved Try to keep things as modular as possible, too In this example, any of the reports can be run as standalone scripts without going through the menu

Using SQL to Write SQL

Another way to branch that also involves a multilevel file structure is simply to spool some output to a new SQL file, then execute that file To implement the security report menu using this technique, you could spool one of three

SELECT statements to a file based on the user's report choice Here's a version of the script that does that:

DESCRIPTION

Print one of three user security reports

SET FEEDBACK OFF

SET PAGESIZE 20

SET LINESIZE 77

SET HEADING ON

Ask the user what report to print

PROMPT

PROMPT 1 - List users

PROMPT 2 - List users and table privileges

PROMPT 3 - List users and system privileges

PROMPT

ACCEPT s_report_choice PROMPT Enter your choice (1,2,3) >

Specify formats for all possible report columns

COLUMN username FORMAT A12 HEADING User

COLUMN privilege FORMAT A20 HEADING Privilege

COLUMN owner FORMAT A12 HEADING Table Owner

COLUMN table_name FORMAT A30 HEADING Table Name

COLUMN error_message FORMAT A40 HEADING Error Message

Set up the page title First we have to get the contents of

b_report_type into a substition variable

Trang 10

set termout off

COLUMN b_report_type FORMAT A30 NOPRINT NEW_VALUE s_report_type

SELECT DECODE (&&s_report_choice,

1,User List,

2,User Table Privileges,

3,User System Privileges,

Invalid Choice) b_report_type

FROM dual;

set termout on

TTITLE LEFT s_report_type RIGHT Page FORMAT 999 SQL.PNO SKIP 2

Generate the query for the report requested by the user

Spool that query to a file

SET TERMOUT OFF

SET PAGESIZE 0

SET HEADING OFF

SET VERIFY OFF

SET FEEDBACK OFF

COLUMN next_query FORMAT A60

SPOOL user_security_choice.sql

This query will be successful if the user chooses 1

SELECT SELECT username ¦¦ CHR(10) ¦¦

FROM dba_users ¦¦ CHR(10) ¦¦

ORDER BY username; ¦¦ CHR(10) next_query

FROM dual

WHERE &&s_report_choice = 1;

This query will be successful if the user chooses 2

SELECT SELECT username, privilege, owner, table_name ¦¦ CHR(10) ¦¦

FROM dba_users, dba_tab_privs ¦¦ CHR(10) ¦¦

WHERE username = grantee ¦¦ CHR(10) ¦¦

ORDER BY username, owner, table_name, privilege;

FROM dual

WHERE &&s_report_choice = 2;

SELECT SELECT username, privilege ¦¦ CHR(10) ¦¦

FROM dba_users, dba_sys_privs ¦¦ CHR(10) ¦¦

WHERE username = grantee ¦¦ CHR(10) ¦¦

ORDER BY username, privilege;

FROM dual

WHERE &&s_report_choice = 3;

SELECT PROMPT You must choose either 1, 2, or 3

FROM dual

WHERE &&s_report_choice NOT IN (1,2,3)

OR &&s_report_choice IS NULL;

SPOOL OFF

SET TERMOUT ON

SET PAGESIZE 20

SET HEADING ON

SET VERIFY ON

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

TỪ KHÓA LIÊN QUAN