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

Oracle Built−in Packages- P20 pps

5 179 0

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

THÔNG TIN TÀI LIỆU

Cấu trúc

  • Table of Contents

  • A. What's on the Companion Disk?

    • A.1 Installing the Guide

    • A.2 Using the Guide

  • 1. Introduction

    • 1.1 The Power of Built-in Packages

      • 1.1.1 A Kinder , More Sharing Oracle

    • 1.2 Built-in Packages Covered in This Book

      • 1.2.1 Application Development Packages

      • 1.2.2 Server Management Packages

      • 1.2.3 Distributed Database Packages

    • 1.3 Using Built-in Packages

      • 1.3.1 What Is a Package?

      • 1.3.2 Controlling Access with Packages

      • 1.3.3 Referencing Built-in Package Elements

      • 1.3.4 Exception Handling and Built-in Packages

      • 1.3.5 Encapsulating Access to the Built-in Packages

      • 1.3.6 Calling Built-in Packaged Code from Oracle Developer/2000 Release 1

      • 1.3.7 Accessing Built-in Packaged Technology from Within SQL

    • 1.4 Examining Built-in Package Source Code

      • 1.4.1 The STANDARD Package

      • 1.4.2 The DBMS_STANDARD Package

  • 2. Executing Dynamic SQL and PL/SQL

    • 2.1 Examples of Dynamic SQL

    • 2.2 Getting Started with DBMS_SQL

      • 2.2.1 Creating the DBMS_SQL Package

      • 2.2.2 Security and Privilege Issues

      • 2.2.3 DBMS_SQL Programs

      • 2.2.4 Types of Dynamic SQL

      • 2.2.5 DBMS_SQL Exceptions

      • 2.2.6 DBMS_SQL Nonprogram Elements

    • 2.3 The DBMS_SQL Interface

      • 2.3.1 Processing Flow of Dynamic SQL

      • 2.3.2 Opening the Cursor

      • 2.3.3 Parsing the SQL Statement

      • 2.3.4 Binding Values into Dynamic SQL

      • 2.3.5 Defining Cursor Columns

      • 2.3.6 Executing the Cursor

      • 2.3.7 Fetching Rows

      • 2.3.8 Retrieving Values

      • 2.3.9 Closing the Cursor

      • 2.3.10 Checking Cursor Status

      • 2.3.11 Describing Cursor Columns

    • 2.4 Tips on Using Dynamic SQL

      • 2.4.1 Some Restrictions

      • 2.4.2 Privileges and Execution Authority with DBMS_SQL

      • 2.4.3 Combining Operations

      • 2.4.4 Minimizing Memory for Cursors

      • 2.4.5 Improving the Performance of Dynamic SQL

      • 2.4.6 Problem-Solving Dynamic SQL Errors

      • 2.4.7 Executing DDL in PL/SQL

      • 2.4.8 Executing Dynamic PL/SQL

    • 2.5 DBMS_SQL Examples

      • 2.5.1 A Generic Drop_Object Procedure

      • 2.5.2 A Generic Foreign Key Lookup Function

      • 2.5.3 A Wrapper for DBMS_SQL .DESCRIBE_COLUMNS

      • 2.5.4 Displaying Table Contents with Method 4 Dynamic SQL

      • 2.5.5 Indirect Referencing in PL/SQL

      • 2.5.6 Array Processing with DBMS_SQL

      • 2.5.7 Using the RETURNING Clause in Dynamic SQL

  • 3. Intersession Communication

    • 3.1 DBMS_PIPE: Communicating Between Sessions

      • 3.1.1 Getting Started with DBMS_PIPE

      • 3.1.2 How Database Pipes Work

      • 3.1.3 Managing Pipes and the Message Buffer

      • 3.1.4 Packing and Unpacking Messages

      • 3.1.5 Sending and Receiving Messages

      • 3.1.6 Tips on Using DBMS_PIPE

      • 3.1.7 DBMS_PIPE Examples

    • 3.2 DBMS_ALERT: Broadcasting Alerts to Users

      • 3.2.1 Getting Started with DBMS_ALERT

      • 3.2.2 The DBMS_ALERT Interface

      • 3.2.3 DBMS_ALERT Examples

  • 4. User Lock and Transaction Management

    • 4.1 DBMS_LOCK: Creating and Managing Resource Locks

      • 4.1.1 Getting Started with DBMS_LOCK

      • 4.1.2 The DBMS_LOCK Interface

      • 4.1.3 Tips on Using DBMS_LOCK

      • 4.1.4 DBMS_LOCK Examples

    • 4.2 DBMS_TRANSACTION: Interfacing to SQL Transaction Statements

      • 4.2.1 Getting Started with DBMS_TRANSACTION

      • 4.2.2 Advising Oracle About In-Doubt Transactions

      • 4.2.3 Committing Data

      • 4.2.4 Rolling Back Changes

      • 4.2.5 Setting Transaction Characteristics

      • 4.2.6 Cleaning Up Transaction Details

      • 4.2.7 Returning Transaction Identifiers

  • 5. Oracle Advanced Queuing

    • 5.1 Oracle AQ Concepts

      • 5.1.1 General Features

      • 5.1.2 Enqueue Features

      • 5.1.3 Dequeue Features

      • 5.1.4 Propagation Features

      • 5.1.5 A Glossary of Terms

      • 5.1.6 Components of Oracle AQ

      • 5.1.7 Queue Monitor

      • 5.1.8 Data Dictionary Views

    • 5.2 Getting Started with Oracle AQ

      • 5.2.1 Installing the Oracle AQ Facility

      • 5.2.2 Database Initialization

      • 5.2.3 Authorizing Accounts to Use Oracle AQ

    • 5.3 Oracle AQ Nonprogram Elements

      • 5.3.1 Constants

      • 5.3.2 Object Names

      • 5.3.3 Queue Type Names

      • 5.3.4 Agents Object Type

      • 5.3.5 Recipient and Subscriber List Table Types

      • 5.3.6 Message Properties Record Type

      • 5.3.7 Enqueue Options Record Type

      • 5.3.8 Dequeue Options Record Type

      • 5.3.9 Oracle AQ Exceptions

    • 5.4 DBMS_AQ: Interfacing to Oracle AQ (Oracle8 only)

      • 5.4.1 Enqueuing Messages

      • 5.4.2 Dequeuing Messages

    • 5.5 DBMS_AQADM: Performing AQ Administrative Tasks (Oracle8 only)

      • 5.5.1 Creating Queue Tables

      • 5.5.2 Creating and Starting Queues

      • 5.5.3 Managing Queue Subscribers

      • 5.5.4 Stopping and Dropping Queues

      • 5.5.5 Managing Propagation of Messages

      • 5.5.6 Verifying Queue Types

      • 5.5.7 Starting and Stopping the Queue Monitor

    • 5.6 Oracle AQ Database Objects

      • 5.6.1 Objects Per Queue Table

      • 5.6.2 Data Dictionary Objects

    • 5.7 Oracle AQ Examples

      • 5.7.1 Improving AQ Ease of Use

      • 5.7.2 Working with Prioritized Queues

      • 5.7.3 Building a Stack with AQ Using Sequence Deviation

      • 5.7.4 Browsing a Queue's Contents

      • 5.7.5 Searching by Correlation Identifier

      • 5.7.6 Using Time Delay and Expiration

      • 5.7.7 Working with Message Groups

      • 5.7.8 Working with Multiple Consumers

  • 6. Generating Output from PL/SQL Programs

    • 6.1 DBMS_OUTPUT: Displaying Output

      • 6.1.1 Getting Started with DBMS_OUTPUT

      • 6.1.2 Enabling and Disabling Output

      • 6.1.3 Writing to the DBMS_OUTPUT Buffer

      • 6.1.4 Retrieving Data from the DBMS_OUTPUT Buffer

      • 6.1.5 Tips on Using DBMS_OUTPUT

      • 6.1.6 DBMS_OUTPUT Examples

    • 6.2 UTL_FILE: Reading and Writing Server-side Files

      • 6.2.1 Getting Started with UTL_FILE

      • 6.2.2 Opening Files

      • 6.2.3 Reading from Files

      • 6.2.4 Writing to Files

      • 6.2.5 Closing Files

      • 6.2.6 Tips on Using UTL_FILE

      • 6.2.7 UTL_FILE Examples

  • 7. Defining an Application Profile

    • 7.1 Getting Started with DBMS_APPLICATION_INFO

      • 7.1.1 DBMS_APPLICATION_INFO Programs

      • 7.1.2 The V$ Virtual Tables

      • 7.1.3 DBMS_APPLICATION_INFO Nonprogram Elements

    • 7.2 DBMS_APPLICATION_INFO Interface

      • 7.2.1 The DBMS_APPLICATION_INFO.READ_CLIENT_INFO procedure

      • 7.2.2 The DBMS_APPLICATION_INFO.READ_MODULE procedure

      • 7.2.3 The DBMS_APPLICATION_INFO.SET_ACTION procedure

      • 7.2.4 The DBMS_APPLICATION_INFO.SET_CLIENT_INFO procedure

      • 7.2.5 The DBMS_APPLICATION_INFO.SET_MODULE procedure

      • 7.2.6 The DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS procedure

    • 7.3 DBMS_APPLICATION_INFO Examples

      • 7.3.1 About the register_app Package

      • 7.3.2 The action Procedure

      • 7.3.3 The set_stats Procedure

      • 7.3.4 The Information Procedures

      • 7.3.5 Using the register_app Package

      • 7.3.6 Covering DBMS_APPLICATION_INFO

      • 7.3.7 Monitoring Application SQL Resource Consumption

      • 7.3.8 Session Monitoring and Three-Tier Architectures

      • 7.3.9 Tracking Long-Running Processes

  • 8. Managing Large Objects

    • 8.1 Getting Started with DBMS_LOB

      • 8.1.1 DBMS_LOB Programs

      • 8.1.2 DBMS_LOB Exceptions

      • 8.1.3 DBMS_LOB Nonprogram Elements

      • 8.1.4 About the Examples

    • 8.2 LOB Concepts

      • 8.2.1 LOB Datatypes

      • 8.2.2 BFILE Considerations

      • 8.2.3 Internal LOB Considerations

    • 8.3 DBMS_LOB Interface

      • 8.3.1 Working with BFILEs

      • 8.3.2 Reading and Examining LOBs

      • 8.3.3 Updating BLOBs, CLOBs, and NCLOBs

  • 9. Datatype Packages

    • 9.1 DBMS_ROWID: Working with the ROWID Pseudo-Column (Oracle8 only)

      • 9.1.1 Getting Started with DBMS_ROWID

      • 9.1.2 ROWID Concepts

      • 9.1.3 The DBMS_ROWID Interface

    • 9.2 UTL_RAW: Manipulating Raw Data

      • 9.2.1 Getting Started with UTL_RAW

      • 9.2.2 Raw Data Manipulation Concepts

      • 9.2.3 The UTL_RAW Interface

      • 9.2.4 UTL_REF: Referencing Objects (Oracle8.0.4)

      • 9.2.5 UTL_REF Interface

      • 9.2.6 UTL_REF Example

  • 10. Miscellaneous Packages

    • 10.1 DBMS_UTILITY: Performing Miscellaneous Operations

      • 10.1.1 Getting Started with DBMS_UTILITY

      • 10.1.2 The DBMS_UTILITY Interface

    • 10.2 DBMS_DESCRIBE: Describing PL/SQL Program Headers

      • 10.2.1 Getting Started with DBMS_DESCRIBE

      • 10.2.2 Explaining DBMS_DESCRIBE Results

      • 10.2.3 DBMS_DESCRIBE Example

    • 10.3 DBMS_DDL: Compiling and Analyzing Objects

      • 10.3.1 Getting Started with DBMS_DDL

      • 10.3.2 Compiling PL/SQL Objects

      • 10.3.3 Computing Statistics for an Object

      • 10.3.4 Setting Referenceability of Tables

    • 10.4 DBMS_RANDOM: Generating Random Numbers (Oracle8 Only)

      • 10.4.1 Getting Started with DBMS_RANDOM

      • 10.4.2 DBMS_RANDOM Interface

  • 11. Managing Session Information

    • 11.1 DBMS_SESSION: Managing Session Information

      • 11.1.1 Getting Started with DBMS_SESSION

      • 11.1.2 Modifying Session Settings

      • 11.1.3 Obtaining Session Information

      • 11.1.4 Managing Session Resources

      • 11.1.5 DBMS_SESSION Examples

    • 11.2 DBMS_System: Setting Events for Debugging

      • 11.2.1 Getting Started with DBMS_SYSTEM

      • 11.2.2 DBMS_SYSTEM Interface

      • 11.2.3 DBMS_SYSTEM Examples

  • 12. Managing Server Resources

    • 12.1 DBMS_SPACE: Obtaining Space Information

      • 12.1.1 Getting Started with DBMS_SPACE

      • 12.1.2 The DBMS_SPACE Interface

      • 12.1.3 DBMS_SPACE Examples

    • 12.2 DBMS_SHARED_POOL: Pinning Objects

      • 12.2.1 Getting Started with DBMS_SHARED_POOL

      • 12.2.2 Pinning and Unpinning Objects

      • 12.2.3 Monitoring and Modifying Shared Pool Behavior

      • 12.2.4 DBMS_SHARED_POOL Examples

  • 13. Job Scheduling in the Database

    • 13.1 Getting Started with DBMS_ JOB

      • 13.1.1 DBMS_JOB Programs

      • 13.1.2 Job Definition Parameters

      • 13.2.1 INIT.ORA Parameters and Background Processes

      • 13.2.2 Job Execution and the Job Execution Environment

      • 13.2.3 Miscellaneous Notes

      • 13.2.4 DBMS_JOB Interface

      • 13.2.5 Submitting Jobs to the Job Queue

      • 13.2.6 Modifying Job Characteristics

      • 13.2.7 Removing Jobs and Changing Job Execution Status

      • 13.2.8 Transferring Jobs

    • 13.2 Job Queue Architecture

    • 13.3 Tips on Using DBMS_JOB

      • 13.3.1 Job Intervals and Date Arithmetic

      • 13.3.2 Viewing Job Information in the Data Dictionary

      • 13.3.3 DBMS_IJOB: Managing Other Users' Jobs

    • 13.4 DBMS_JOB Examples

      • 13.4.1 Tracking Space in Tablespaces

      • 13.4.2 Fixing Broken Jobs Automatically

      • 13.4.3 Self-Modifying and Self-Aware Jobs

  • 14. Snapshots

    • 14.1 DBMS_SNAPSHOT: Managing Snapshots

      • 14.1.1 Getting Started with DBMS_SNAPSHOT

      • 14.1.2 Using the I_AM_A_REFRESH Package State Variable

      • 14.1.3 Refreshing Snapshots

      • 14.1.4 Purging the Snapshot Log

      • 14.1.5 Reorganizing Tables

      • 14.1.6 Registering Snapshots

      • 14.2.1 Getting Started with DBMS_REFRESH

      • 14.2.2 Creating and Destroying Snapshot Groups

      • 14.2.3 Adding and Subtracting Snapshots from Snapshot Groups

      • 14.2.4 Altering Properties of a Snapshot Group

      • 14.2.5 Manually Refreshing Snapshot Groups

    • 14.2 DBMS_REFRESH: Managing Snapshot Groups

    • 14.3 DBMS_OFFLINE_SNAPSHOT: Performing Offline Snapshot Instantiation

      • 14.3.1 Getting Started with DBMS_OFFLINE_SNAPSHOT

      • 14.3.2 DBMS_OFFLINE_SNAPSHOT Interface

    • 14.4 DBMS_REPCAT: Managing Snapshot Replication Groups

      • 14.4.1 Getting Started with DBMS_REPCAT

      • 14.4.2 Creating and Dropping Snapshot Replication Groups

      • 14.4.3 Adding and Removing Snapshot Replication Group Objects

      • 14.4.4 Altering a Snapshot Replication Group's Propagation Mode

      • 14.4.5 Manually Refreshing a Snapshot Replication Group

      • 14.4.6 Switching the Master of a Snapshot Replication Group

  • 15. Advanced Replication

    • 15.1 DBMS_REPCAT_AUTH: Setting Up Administrative Accounts

      • 15.1.1 Getting Started with DBMS_REPCAT_AUTH

      • 15.1.2 Granting and Revoking Surrogate SYS Accounts

      • 15.1.3 Granting and Revoking Propagator Accounts (Oracle8)

    • 15.2 DBMS_REPCAT_ADMIN: Setting Up More Administrator Accounts

      • 15.2.1 Getting Started with DBMS_REPCAT_ADMIN

      • 15.2.2 Creating and Dropping Replication Administrator Accounts

    • 15.3 DBMS_REPCAT: Replication Environment Administration

      • 15.3.1 Getting Started with DBMS_REPCAT

      • 15.3.2 Replication Groups with DBMS_REPCAT

      • 15.3.3 Replicated Objects with DBMS_REPCAT

      • 15.3.4 Replication Support with DBMS_REPCAT

      • 15.3.5 Adding and Removing Master Sites with DBMS_REPCAT

      • 15.3.6 Maintaining the Repcatlog Queue with DBMS_REPCAT

      • 15.3.7 Quiescence with DBMS_REPCAT

      • 15.3.8 Miscellaneous DBMS_REPCAT Procedures

    • 15.4 DBMS_OFFLINE_OG: Performing Site Instantiation

      • 15.4.1 Getting Started with DBMS_OFFLINE_OG

      • 15.4.2 DBMS_OFFLINE_OG Interface

    • 15.5 DBMS_RECTIFIER_DIFF: Comparing Replicated Tables

      • 15.5.1 Getting Started with DBMS_RECTIFIER_DIFF

      • 15.5.2 DBMS_RECTIFIER_DIFF Interface

    • 15.6 DBMS_REPUTIL: Enabling and Disabling Replication

      • 15.6.1 Getting Started with DBMS_REPUTIL

      • 15.6.2 DBMS_REPUTIL Interface

  • 16. Conflict Resolution

    • 16.1 Getting Started with DBMS_REPCAT

      • 16.1.1 DBMS_REPCAT Programs

      • 16.1.2 DBMS-REPCAT Exceptions

      • 16.1.3 DBMS-REPCAT Nonprogram Elements

      • 16.1.4 Data Dictionary Views

    • 16.2 Column Groups with DBMS_REPCAT

      • 16.2.1 About Column Groups

      • 16.2.2 Creating and Dropping Column Groups

      • 16.2.3 Modifying Existing Column Groups

    • 16.3 Priority Groups with DBMS_REPCAT

      • 16.3.1 About Priority Groups

      • 16.3.2 Creating, Maintaining, and Dropping Priority Groups

      • 16.3.3 Creating and Maintaining Priorities Within a Priority Group

      • 16.3.4 Dropping Priorities from a Priority Group

    • 16.4 Site Priority Groups with DBMS_REPCAT

      • 16.4.1 About Site Priority Groups

      • 16.4.2 Creating, Maintaining, and Dropping Site Priorities

      • 16.4.3 Maintaining Site Priorities

    • 16.5 Assigning Resolution Methods with DBMS_REPCAT

      • 16.5.1 About Resolution Methods

    • 16.6 Monitoring Conflict Resolution with DBMS_REPCAT

      • 16.6.1 About Monitoring

  • 17. Deferred Transactions and Remote Procedure Calls

    • 17.1 About Deferred Transactions and RPCs

      • 17.1.1 About Remote Destinations

      • 17.1.2 Data Dictionary Views

    • 17.2 DBMS_DEFER_SYS: Managing Deferred Transactions

      • 17.2.1 Getting Started with DBMS_DEFER_SYS

      • 17.2.2 Adding and Deleting Default Destinations

      • 17.2.3 Copying Deferred Transactions to New Destinations

      • 17.2.4 Maintenance Procedures

      • 17.2.5 Propagating Deferred RPCs

      • 17.2.6 Scheduling Propagation (Oracle8 only)

    • 17.3 DBMS_DEFER: Building Deferred Calls

      • 17.3.1 Getting Started with DBMS_DEFER

      • 17.3.2 Basic RPCs

      • 17.3.3 Parameterized RPCs

    • 17.4 DBMS_DEFER_QUERY: Performing Diagnostics and Maintenance

      • 17.4.1 Getting Started with DBMS_DEFER_QUERY

    • Table of Contents

      • Part I: Overview

      • Part II: Application Development Packages

      • Part III: Server Management Packages

      • Part IV: Distributed Database Packages

  • Structure of This Book

Nội dung

that most wonderful of PL/SQL constructs, the package. Among other great features, the Janfast/jandyn package she developed contains a procedure called create_index to create an index for any table and column(s) on the table. The code for this procedure is shown at the beginning of this chapter. Jan installed the Janfast/jandyn package in the JANDBA account (what can I say? She likes her name!) and granted EXECUTE privilege on that package to all users, including her account named (yep, you guessed it) JAN. To make things even more exciting, she built an Oracle Forms front−end to her package (Janfast/jandyn). She could then take advantage of the stored code through a fill−in−the−form interface, rather than the command−line approach of SQL*Plus. One day Jan receives a call: it seems that the company has added many employees over the years, and the emp table now has six million rows. All of the user accounts (working against a shared data source in the PERSONNEL Oracle account) are experiencing serious performance problems. A new index (at least one) is needed on the emp table to improve query performance. So Jan connects to the production PERSONNEL account and starts up Janfast/jandyn. Just a few keystrokes and mouse clicks later, she has constructed the following statement, jandyn.create_index ('empname_idx', 'emp', 'ename, sal'); which is to say: create an index named empname_idx on the emp table on the ename and sal columns (in that order). She clicks on the Execute button and Janfast does its thing. Notified through a chime of the successful completion of her task, Jan is impressed at how rapidly the index was built. She notifies the application development team that all is better now. Fifteen minutes of quiet contemplation pass before she gets an angry call from a developer: "The performance hasn't changed one bit!" he says angrily. "The screens still work just as slowly as before when I try to search for an employee by name." Jan the DBA is bewildered and quickly runs the following script to examine the indexes on the emp table: SQL> SELECT i.index_name, i.tablespace_name, uniqueness u, column_name col, column_position pos FROM all_indexes i, all_ind_columns c WHERE i.index_name = c.index_name AND i.table_name = 'EMP'; INDEX_NAME TABLESPACE_NAME U COL POS −−−−−−−−−−−−−−−− −−−−−−−−−−−−−−−−−−−− −−−−−−−−− −−−−−−−−− −−− EMP_PRIMARY_KEY USER_DATA UNIQUE EMPNO 1 There is no empname_idx index! What has gone wrong? Where did the index go? How and why did Janfast/jandyn fail our industrious and creative database administrator? Remember: when you execute stored code, you run it under the privileges of the owner of that code, not the privileges of the account that called the program. When Jan executed the index creation statement from within a call to jandyn.creind, the DDL statement was processed as though it were being executed by JANDBA, not by PERSONNEL. If the DBA had wanted to create an index in her own schema, she should have entered the following command: jandyn.creind ('personnel.empname_idx', 'personnel.emp', 'ename, sal'); If this command had been executed, Jan would have had a much better chance at solving her performance problems. [Appendix A] What's on the Companion Disk? 86 2.4.2.2 The tale of Scott Here's another common gotcha: my SCOTT account has been granted the standard CONNECT and RESOURCE roles. As a result, I can create a table as follows: SQL> CREATE TABLE upbeat (tempo NUMBER); Table created Now suppose that I have created a little program to make it easier for me to execute DDL from within PL/SQL: /* Filename on companion disk: runddl.sp */* CREATE OR REPLACE PROCEDURE runddl (ddl_in in VARCHAR2) IS cur INTEGER:= DBMS_SQL.OPEN_CURSOR; fdbk INTEGER; BEGIN DBMS_SQL.PARSE (cur, ddl_in, DBMS_SQL.V7); fdbk := DBMS_SQL.EXECUTE (cur); DBMS_SQL.CLOSE_CURSOR (cur); END; / I then issue the same CREATE TABLE statement as before, this time within PL/SQL, but now I get an error: SQL> exec runddl ('CREATE TABLE upbeat (tempo NUMBER)'); * ERROR at line 1: ORA−01031: insufficient privileges ORA−06512: at "SYS.DBMS_SYS_SQL", line 239 Don't beat your head against the wall when this happens! Just remember that role−based privileges do not help you when executing SQL from within PL/SQL. The RESOURCE role is ignored when the CREATE TABLE statement is executed. SCOTT doesn't have any CREATE TABLE privileges, so the dynamic SQL fails. 2.4.3 Combining Operations Every PARSE must be preceded by a call to OPEN_CURSOR. Every call to PARSE must include a DBMS mode argument, even though 99.99% of the time, it is going to be DBMS_SQL.NATIVE. When I find myself repeating the same steps over and over again in using a package or particular feature, I look for ways to bundle these steps into a single procedure or function call to save myself time. The next function shows such a function, open_and_parse, which opens a cursor and parses the specified SQL statement. Using open_and_parse, I can replace the following statements, cursor_handle := DBMS_SQL.OPEN_CURSOR; DBMS_SQL.PARSE (cursor_handle, 'UPDATE emp ', DBMS_SQL.NATIVE); with just this: cursor_handle := open_and_parse ('UPDATE emp '); Here, then, is the open_and_parse bundled procedure: /* Filename on companion disk: openprse.sf */* CREATE OR REPLACE FUNCTION open_and_parse (sql_statement_in IN VARCHAR2, [Appendix A] What's on the Companion Disk? 2.4.2 Privileges and Execution Authority with DBMS_SQL 87 dbms_mode_in IN INTEGER := DBMS_SQL.NATIVE) RETURN INTEGER IS /* Declare cursor handle and assign it a pointer */ return_value INTEGER := DBMS_SQL.OPEN_CURSOR; BEGIN /* Parse the SQL statement */ DBMS_SQL.PARSE (return_value, sql_statement_in, dbms_mode_in); /* Pass back the pointer to this parsed statement */ RETURN return_value; END; Now, one problem with this otherwise handy little procedure is that it always declares a new cursor. What if you already have a cursor? Then you should go straight to the parse step. You can combine the functionality of open_and_parse with the initcur procedure shown in the next section to produce your own enhanced program. 2.4.4 Minimizing Memory for Cursors As noted earlier, you will not want to allocate a cursor via the OPEN_CURSOR procedure if you can instead use an already defined cursor that is not currently in use. The best way to minimize memory usage with dynamic SQL cursors is to encapsulate the open action inside a procedure. The initcur procedure shown below demonstrates this technique. With initcur, you pass a variable into the procedure. If that variable points to a valid, open DBMS_SQL cursor, then it is returned unchanged. If, on the other hand, that cursor is closed (the IS_OPEN function returns FALSE) or IS_OPEN for any reason raises the INVALID_CURSOR exception, then OPEN_CURSOR is called and the new cursor pointer is returned. CREATE OR REPLACE PROCEDURE initcur (cur_inout IN OUT INTEGER) IS BEGIN IF NOT DBMS_SQL.IS_OPEN (cur_inout) THEN cur_inout := DBMS_SQL.OPEN_CURSOR; END IF; EXCEPTION WHEN invalid_cursor THEN cur_inout := DBMS_SQL.OPEN_CURSOR; END; / You could also implement this functionality as a function, or could overload both inside a package, as follows: CREATE OR REPLACE PACKAGE dyncur IS PROCEDURE initcur (cur_inout IN OUT INTEGER); FUNCTION initcur (cur_in IN INTEGER) RETURN INTEGER; END dyncur; / In addition to allocating cursor areas only when necessary, you should make sure that you close your cursors when you are done with them. Unlike static cursors, which close automatically when their scope terminates, a dynamic SQL cursor will remain open even if the block in which it was defined finishes execution. And remember that you should perform the close operation at the end of the executable code, but also in any exception sections in the block. This technique is shown here: CREATE OR REPLACE PROCEDURE do_dynamic_stuff [Appendix A] What's on the Companion Disk? 2.4.4 Minimizing Memory for Cursors 88 IS cur1 INTEGER := DBMS_SQL.OPEN_CURSOR; cur2 INTEGER := DBMS_SQL.OPEN_CURSOR; PROCEDURE closeall IS BEGIN /* Only close if open. Defined in Closing the Cursor section. */ closeif (cur1); closeif (cur2); END; BEGIN /* Do the dynamic stuff, then close the cursors.*/ closeall; EXCEPTION WHEN DUP_VAL_ON_INDEX THEN /* Special handling, then cleanup */ closeall; WHEN OTHERS THEN /* Catch−all cleanup, then reraise to propagate out the error.*/ closeall; RAISE; END; / The openprse.ssp file contains a package that implements both the initcur and an enhanced version of open_and_parse (see the section called Section 2.4.3, "Combining Operations"). This package allows you to keep to an absolute minimum the number of cursors allocated to perform dynamic SQL operations. 2.4.5 Improving the Performance of Dynamic SQL You can improve the performance of your dynamic SQL operations by taking advantage of two aspects of DBMS_SQL: • Reuse DBMS_SQL cursors whenever possible (this technique was demonstrated in the last section). • Avoid reparsing your dynamic SQL when the only thing that changes is a bind variable. The following script (written with the help of John Beresniewicz) demonstrates the gains you can see by paying attention to both of these considerations. The script illustrates three different ways to do the same thing in dynamic SQL using DBMS_SQL, namely fetch rows from a table. • Approach 1 parses and executes each query without using any bind variables. It is the most inefficient, performing 1000 parses, executing 1000 statements, and requiring room in the shared pool for up to 1000 different SQL statements. • Approach 2 parses and executes for each query, but uses bind variables, so it works a bit more efficiently. With this approach, you still perform 1000 parses and execute 1000 times, but at least you need room for only one SQL statement in the shared pool. • [Appendix A] What's on the Companion Disk? 2.4.5 Improving the Performance of Dynamic SQL 89 Approach 3 parses just once and executes each query using host variables. It is by far the most efficient technique: requiring just one parse, 1000 executions, and a single preparsed SQL statement in the shared pool. I have used a very large and cumbersome SELECT in this test to make sure that there was enough overhead in parsing to both simulate a "real−world" query and also to demonstrate a clear difference in performance between the second and third approaches (for very simple SQL statements, you will not see too much of a difference). For the sake of brevity, I will not show the entire query in the code. /* Filename on companion disk: effdsql.tst */* DECLARE /* || Approach 1: the worst */ v_start INTEGER; cursor_id INTEGER; exec_stat INTEGER; BEGIN v_start := DBMS_UTILITY.GET_TIME; cursor_id := DBMS_SQL.OPEN_CURSOR; FOR i IN 1 &1 LOOP /* || parse and excecute each loop iteration || without using host vars, this is worst case */ DBMS_SQL.PARSE (cursor_id, 'SELECT ', DBMS_SQL.native); exec_stat := DBMS_SQL.EXECUTE(cursor_id); END LOOP; DBMS_SQL.CLOSE_CURSOR(cursor_id); DBMS_OUTPUT.PUT_LINE ('Approach 1: ' || TO_CHAR (DBMS_UTILITY.GET_TIME − v_start)); END; / DECLARE /* || Approach 2: a little better */ v_start INTEGER; cursor_id INTEGER; exec_stat INTEGER; BEGIN v_start := DBMS_UTILITY.GET_TIME; cursor_id := DBMS_SQL.OPEN_CURSOR; FOR i IN 1 &1 LOOP /* || parse and excecute each loop iteration using host vars */ DBMS_SQL.PARSE (cursor_id, 'SELECT ', DBMS_SQL.native); DBMS_SQL.BIND_VARIABLE(cursor_id,'i',i); exec_stat := DBMS_SQL.EXECUTE(cursor_id); END LOOP; DBMS_SQL.CLOSE_CURSOR(cursor_id); DBMS_OUTPUT.PUT_LINE ('Approach 2: ' || TO_CHAR (DBMS_UTILITY.GET_TIME − v_start)); END; / DECLARE /* || Approach 3: the best */ v_start INTEGER; cursor_id INTEGER; exec_stat INTEGER; [Appendix A] What's on the Companion Disk? 2.4.5 Improving the Performance of Dynamic SQL 90 . including her account named (yep, you guessed it) JAN. To make things even more exciting, she built an Oracle Forms front−end to her package (Janfast/jandyn). She could then take advantage of the stored. six million rows. All of the user accounts (working against a shared data source in the PERSONNEL Oracle account) are experiencing serious performance problems. A new index (at least one) is needed

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

TỪ KHÓA LIÊN QUAN