4 - Oracle Database 11g Advanced PLSQL Vol 1 and 2
4 - Oracle Database 11g Advanced PLSQL Vol 1 and 2
4 - Oracle Database 11g Advanced PLSQL Vol 1 and 2
Introduction
SYSTOOLS
Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Course Objectives
SYSTOOLS
After completing this course, you should be able to do the
following:
• Design PL/SQL packages and program units that execute
efficiently
• Write code to interface with external applications and the
operating system
• Create PL/SQL applications that use collections
• Write and tune PL/SQL code effectively to maximize
performance
• Implement a virtual private database with fine-grained
SYSTOOLS
access control
• Write code to interface with large objects and use SecureFile
LOBs
• Perform code analysis to find program ambiguities, test,
trace, and profile PL/SQL code
Course Objectives
In this course, you learn how to use the advanced features of PL/SQL in order to design and tune
PL/SQL to interface with the database and other applications in the most efficient manner. Using the
advanced features of program design, packages, cursors, extended interface methods, and collections,
you learn how to write powerful PL/SQL programs. Programming efficiency, use of external C and
SYSTOOLS
Java routines, and fine-grained access are covered in this course.
SYSTOOLS Clients
Development tools
System management
Internet applications
SQL
Business logic Presentation and
and data business logic PL/SQL
SYSTOOLS
Databases Application
servers
Network services
Other
Java
SYSTOOLS
• Databases to execute database-intensive business logic and serve data
Oracle offers a wide variety of the most advanced graphical user interface (GUI)–driven
development tools to build business applications, as well as a large suite of software applications for
many areas of business and industry. Stored procedures, functions, and packages can be written by
using SQL, PL/SQL, Java, C, and Net languages. This course concentrates on the advanced features
of PL/SQL.
•
•
SYSTOOLS
Previewing the course agenda
Describing the development environments
• Using SQL Developer
• Using SQL*Plus
• Identifying the tables, data, and tools used in this course
SYSTOOLS
1-4 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
• Day 1
–
SYSTOOLS
Lesson 1: Introduction
– Lesson 2: PL/SQL Review
– Lesson 3: Designing PL/SQL Code
– Lesson 4: Working with Collections
• Day 2
– Lesson 4: Working with Collections
– Lesson 5: Using Advanced Interface Methods
– Lesson 6: Implementing Fine-Grained Access Control for VPD
SYSTOOLS
– Lesson 7: Manipulating Large Objects
– Lesson 8: Administering SecureFile LOBs
– Lesson 9: Performance and Tuning
Agenda
In this three-day course, you start with a review of PL/SQL concepts before progressing into the new
and advanced topics. By the end of day one, you should have covered design considerations for your
program units, and how to use collections effectively.
On day two, you learn how to use advanced interface methods to call C and Java code from your
SYSTOOLS
PL/SQL programs, how to implement and test fine-grained access control for virtual private
databases, how to manipulate large objects programmatically through PL/SQL, how to administer the
features of the new SecureFile LOB format of Database 11g, and how to tune PL/SQL code and deal
with memory issues.
• Day 3
–
SYSTOOLS
Lesson 10: Improving Performance with Caching
– Lesson 11: Analyzing PL/SQL Code
– Lesson 12: Profiling and Tracing PL/SQL Code
– Lesson 13: Safeguarding Your Code Against SQL Injection
Attacks
SYSTOOLS
1-6 Copyright © 2008, Oracle. All rights reserved.
Agenda (continued)
On day three, you learn how to improve performance by using Oracle database 11g caching
techniques, how to write PL/SQL routines that analyze PL/SQL applications, how to profile and trace
PL/SQL code, and how to protect your code from SQL injection security attacks.
SYSTOOLS
•
•
SYSTOOLS
Previewing the course agenda
Describing the development environments
• Using SQL Developer
• Using SQL*Plus
• Identifying the tables, data, and tools used in this course
SYSTOOLS
1-7 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• Introduction to SQL Developer
• SQL*Plus
SYSTOOLS
SQL Developer
SYSTOOLS
Note: The code and screen examples presented in the course notes were generated from the output in
the SQL Developer environment.
•
•
SYSTOOLS
Previewing the course agenda
Describing the development environments
• Using SQL Developer
• Using SQL*Plus
• Identifying the tables, data, and tools used in this course
SYSTOOLS
1-9 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• Oracle SQL Developer is a free graphical tool that enhances
productivity and simplifies database development tasks.
• You can connect to any target Oracle database schema by
using the standard Oracle database authentication.
• You can use either SQL Developer or SQL*Plus in this
course.
SYSTOOLS
• Browsing and managing database objects
• Executing SQL statements and scripts
• Editing and debugging PL/SQL statements
• Creating reports
You can connect to any target Oracle database schema by using the standard Oracle database
authentication. When connected, you can perform operations on the objects in the database.
SYSTOOLS
Creating a Database Connection
1
3
SYSTOOLS 4 5
SYSTOOLS
want to connect to.
4. Click Test to make sure that the connection is set correctly.
5. Click Connect.
On the basic tabbed page, at the bottom, enter the following options:
• Hostname: Host system for the Oracle database
• Port: Listener port
• SID: Database name
• Service Name: Network service name for a remote database connection
If you select the Save Password check box, the password is saved to an XML file. After you close the
SQL Developer connection and open it again, you are not prompted for the password.
SYSTOOLS
• You can create any schema object in SQL Developer by
using one of the following methods:
– Executing a SQL statement in the SQL worksheet
– Using the context menu
• Edit the objects by using an edit dialog box or one of the
many context-sensitive menus
• View the DDL for adjustments such as creating a new object
or editing an existing schema object
SYSTOOLS
1 - 12 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• Use the SQL worksheet to enter and execute SQL, PL/SQL,
and SQL*Plus statements.
• Specify any actions that can be processed by the database
connection associated with the worksheet.
SYSTOOLS
Select SQL
Worksheet from the
Tools menu, or
SYSTOOLS
SQL worksheet supports some SQL*Plus statements. However, SQL*Plus statements that are not
supported by the SQL worksheet are ignored and not passed to the database.
You can specify any actions that can be processed by the database connection associated with the
worksheet, such as:
• Creating a table
• Inserting data
• Creating and editing a trigger
• Selecting data from a table
• Saving the selected data to a file
You can display a SQL worksheet by using one of the following options:
• Select Tools > SQL Worksheet.
• Click the Open SQL Worksheet icon.
SYSTOOLS
2 4 6 8
1 3 5 7 9
SYSTOOLS
1 - 14 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
can use bind variables in the SQL statements. You cannot use substitution variables.
2. Run Script: Executes all statements in the Enter SQL Statement box by using the Script.
Runner. You can use substitution variables in the SQL statements. You cannot use bind
variables.
3. Commit: Writes changes to the database and ends the transaction.
4. Rollback: Discards changes to the database without writing them to the database, and ends the
transaction.
5. Cancel: Stops the execution of statements that are being executed.
6. SQL History: Displays a dialog box with information about the SQL statements that you
executed.
7. Execute Explain Plan: Generates the execution plan, which you can see by clicking the Explain
tab.
8. Autotrace: Generates trace information for the statement.
9. Clear: Erases the statement or statements in the Enter SQL Statement box.
SYSTOOLS
Use the Enter SQL Statement box to enter single or multiple
SQL statements.
SYSTOOLS
View the results on
the Script Output
tabbed page.
SYSTOOLS
Alternatively, you can press F9.
To execute multiple SQL statements and see the results, click the Run Script icon. Alternatively,
you can press F5.
In the example in the slide, because there are multiple SQL statements, the first statement is
terminated with a semicolon. The cursor is in the first statement, and therefore, when the statement is
executed, results corresponding to the first statement are displayed in the Results box.
SYSTOOLS
Click Open.
SYSTOOLS
2. In the Open dialog box, select (or navigate to) the script file that you want to open.
3. Click Open. The code of the script file is displayed in the SQL worksheet area.
4. To run the code, click the Run Script (F5) icon on the SQL worksheet toolbar.
SYSTOOLS
1 - 17 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
The results from running the file are displayed on the Script Output tabbed page. You can also save
the script output by clicking the Save icon on the Script Output tabbed page. The Windows File Save
dialog box appears and you can identify a name and location for your file.
SYSTOOLS
Create an anonymous block and display the output of the
DBMS_OUTPUT package.
SYSTOOLS
1 - 18 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
2. Click the DBMS Output tab. Click the Enable DBMS Output icon to set the server output ON.
3. Click the Execute Statement icon above the Enter SQL Statement box. Click the DBMS
Output tab to see the results.
SYSTOOLS
Use the full-featured editor for PL/SQL program units.
SYSTOOLS
1 - 19 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
• Code Completion
• Code Folding
• Search and Replace
To edit the PL/SQL code, click the object name in the Connections Navigator, and then click the
Edit icon. Optionally, double-click the object name to invoke the Object Definition page with its tabs
and the Edit page. You can update only if you are on the Edit tabbed page.
The slide shows the Code Insight feature. For example, if you enter DBMS_OUTPUT, and then press
Ctrl + Spacebar, you can select from a list of members of that package. Note that, by default, Code
Insight is invoked automatically if you pause after entering a period (“.”) for more than one second.
When using the Code Editor to edit PL/SQL code, you can use Compile or Compile for Debug. Use
the Compile for Debug option if you plan on using the SQL Developer Debugger. This option adds
some debugging directives.
SYSTOOLS
Click the Save icon to
save your SQL
statement to a file.
Enter a file name and
identify a location to
save the file in, and
then click Save.
SYSTOOLS
1 - 20 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
file.
3. Click Save.
After you save the contents to a file, the Enter SQL Statement box displays a tabbed page of your file
contents. You can have multiple files open simultaneously. Each file is displayed as a tabbed page.
Script Pathing
You can select a default path to look for scripts and to save scripts. Under Tools > Preferences >
Database > Worksheet Parameters, enter a value in the Select default path to look for scripts
field.
SYSTOOLS
• Use SQL Developer to debug PL/SQL functions and
procedures.
• Use the Compile for Debug option to perform a PL/SQL
compilation so that the procedure can be debugged.
• Use the Debug menu options to set breakpoints, and to
perform step into and step
over tasks.
SYSTOOLS
1 - 21 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
• Step Over bypasses the next method and goes to the next statement after the method.
• Step Into goes to the first statement in the next method.
• Step Out leaves the current method and goes to the next statement.
• Step to End of Method goes to the last statement of the current method.
• Pause halts execution but does not exit, thus allowing you to resume execution.
• Terminate halts and exits the execution. You cannot resume execution from this point; instead,
to start running or debugging from the beginning of the function or procedure, click the Run or
Debug icon on the Source tab toolbar.
• Garbage Collection removes invalid objects from the cache in favor of the more frequently
accessed and more valid objects.
•
•
SYSTOOLS
Previewing the course agenda
Describing the development environments
• Using SQL Developer
• Using SQL*Plus
• Identifying the tables, data, and tools used in this course
SYSTOOLS
1 - 22 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• You can invoke the SQL*Plus command-line interface from
SQL Developer.
• Close all SQL worksheets to enable the SQL*Plus menu
option.
Provide the
location of the
sqlplus.exe
Using SQL*Plus
The SQL worksheet supports most of the SQL*Plus statements. SQL*Plus statements must be
interpreted by the SQL worksheet before being passed to the database; any SQL*Plus statements that
are not supported by the SQL worksheet are ignored and not passed to the database. To display the
SQL*Plus command window, from the Tools menu, select SQL*Plus. To use the SQL*Plus
SYSTOOLS
command-line interface within SQL Developer, the system on which you are using SQL Developer
must have an Oracle home directory or folder, with a SQL*Plus executable under that location. If the
location of the SQL*Plus executable is not already stored in your SQL Developer preferences, you
are asked to specify its location.
For example, some of the SQL*Plus statements that are not supported by SQL worksheet are:
• append
• archive
• attribute
• break
For a complete list of SQL*Plus statements that are either supported or not supported by the SQL
worksheet, refer to the “SQL*Plus Statements Supported and Not Supported in SQL Worksheet”
topic in the SQL Developer online Help.
SYSTOOLS
SYSTOOLS
1 - 24 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SQL*Plus is:
• Shipped with the database
• Installed on a client and on the database server system
• Accessed from an icon or the command line
When coding PL/SQL subprograms by using SQL*Plus, remember the following:
• You create subprograms by using the CREATE SQL statement.
• You execute subprograms by using either an anonymous PL/SQL block or the EXECUTE
command.
• If you use the DBMS_OUTPUT package procedures to print text to the screen, you must first
execute the SET SERVEROUTPUT ON command in your session.
•
•
SYSTOOLS
Previewing the course agenda
Describing the development environments
• Using SQL Developer
• Using SQL*Plus
• Identifying the tables, data, and tools used in this course
SYSTOOLS
1 - 25 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• The sample schemas used are:
– Order Entry (OE) schema
– Human Resources (HR) schema
• Primarily, the OE schema is used.
• The OE schema user can read data in the HR schema tables.
• Appendix B contains more information about the sample
schemas.
SYSTOOLS
1 - 26 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
• The Order Entry division tracks product inventories and sales of the company’s products through
various channels.
• The Sales History division tracks business statistics to facilitate business decisions. Although not
used in this course, the SH schema is part of the “Example” sample schemas shipped with the
database.
Each of these divisions is represented by a schema.
This course primarily uses the Order Entry (OE) sample schema.
Note: More details about the sample schema are found in Appendix B.
All scripts necessary to create the OE schema reside in the
$ORACLE_HOME/demo/schema/order_entry folder.
All scripts necessary to create the HR schema reside in the
$ORACLE_HOME/demo/schema/human_resources folder.
SYSTOOLS OE
PROMOTIONS
promo_id
promo_name
CUSTOMERS
customer_id
customer_first_name
customer_last_name
cust_address_typ
ORDERS street_address
order_id postal_code
ORDER_ITEMS city
order_date
order_id state_province
order_mode
line_item_id country_id
customer_id
product_id
order_status
unit_price phone_numbers
order_total
quantity nls_language
sales_rep_id
promotion_id nls_territory
credit_limit
cust_email
CATEGORIES_ PRODUCT_ PRODUCT_ account_mgr_id
TAB INFORMATION DESCRIPTIONS cust_geo_location
category_id product_id product_id date_of_birth
category_name product_name language_id marital_status
category_description product_description translated_name gender
SYSTOOLS
parent_category_id category_id translated_description income_level
weight_class
warranty_period
supplier_id WAREHOUSES
INVENTORIES
product_status warehouse_id
product_id
list_price warehouse_spec
warehouse_id
min_price warehouse_name
quantity_on_hand
catalog_url location_id
wh_geo_location
SYSTOOLS
which a product will be sold, and a URL address for manufacturer information.
Inventory information is also recorded for all products, including the warehouse where the product is
available and the quantity on hand. Because products are sold worldwide, the company maintains the
names of the products and their descriptions in several different languages.
The company maintains warehouses in several locations to facilitate filling customer orders. Each
warehouse has a warehouse identification number, name, and location identification number.
SYSTOOLS
phone numbers for each customer), and postal code. Some customers order through the Internet, so
email addresses are also recorded. Because of language differences among customers, the company
records the NLS language and territory of each customer. The company places a credit limit on its
customers to limit the amount for which they can purchase at one time. Some customers have
account managers, whom the company monitors. It keeps track of a customer’s phone number. At
present, you do not know how many phone numbers a customer might have, but you try to keep track
of all of them. Because of the language differences among our customers, you also identify the
language and territory of each customer.
When a customer places an order, the company tracks the date of the order, the mode of the order,
status, shipping mode, total amount of the order, and the sales representative who helped place the
order. This may be the same individual as the account manager for a customer, it may be someone
else, or, in the case of an order over the Internet, the sales representative is not recorded. In addition
to the order information, the company also tracks the number of items ordered, the unit price, and the
products ordered.
SYSTOOLS
For each country in which it does business, the company records the country name, currency symbol,
currency name, and the region where the country resides geographically. This data is useful to
interact with customers who are living in different geographic regions of the world.
SYSTOOLS
SYSTOOLS
SYSTOOLS
1 - 29 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
identification code, job title, and a minimum and maximum salary range for the job. Some employees
have been with the company for a long time and have held different positions within the company.
When an employee switches jobs, the company records the start date and end date of the former job,
the job identification number, and the department.
The sample company is regionally diverse, so it tracks the locations of not only its warehouses but
also its departments. Each company employee is assigned to a department. Each department is
identified by a unique department number and a short name. Each department is associated with one
location. Each location has a full address that includes the street address, postal code, city, state or
province, and country code.
For each location where it has facilities, the company records the country name, currency symbol,
currency name, and the region where the country resides geographically.
Note: For more information about the “Example” sample schemas, refer to Appendix B.
SYSTOOLS
In this lesson, you should have learned how to:
• Describe the goals of the course
• Identify the environments that can be used in this course
• Describe the database schema and tables that are used in
the course
• List the available documentation and resources
SYSTOOLS
1 - 30 Copyright © 2008, Oracle. All rights reserved.
Summary
In this lesson, you were introduced to the goals of the course, the SQL Developer and SQL*Plus
environments used in the course, and the database schema and tables used in the lectures and lab
practices.
SYSTOOLS
SYSTOOLS
This practice covers the following topics:
• Reviewing the available SQL Developer resources
• Starting SQL Developer and creating new database
connections and browsing the HR, OE, and SH tables
• Setting some SQL Developer preferences
• Executing SQL statements and an anonymous PL/SQL block
by using SQL worksheet
• Accessing and bookmarking the Oracle Database 11g
documentation and other useful Web sites
SYSTOOLS
1 - 31 Copyright © 2008, Oracle. All rights reserved.
Practice 1: Overview
In this practice, you use SQL Developer to execute SQL statements for examining the data in the
“Example” sample schemas: HR, OE, and SH. You also create a simple anonymous block. Optionally,
you can experiment by creating and executing the PL/SQL code in SQL*Plus.
Note: All written practices use SQL Developer as the development environment. Although it is
SYSTOOLS
recommended that you use SQL Developer, you can also use the SQL*Plus environment that is
available in this course.
SYSTOOLS
lesson.
In this practice, you review the available SQL Developer resources. You also learn about the user
account that you use in this course. You start SQL Developer, create a new database connection, and
browse your SH, HR, and OE tables. You also set some SQL Developer preferences, execute SQL
statements, access and bookmark the Oracle Database 11g documentation and other useful Web sites
that you can use in this course.
Identifying the Available SQL Developer Resources
1. Familiarize yourself with Oracle SQL Developer as needed by referring to Appendix C: Using
SQL Developer.
2. Access the SQL Developer Home page that is available online at:
http://www.oracle.com/technology/products/database/sql_developer/index.html
3. Bookmark the page for easier future access.
4. Access the SQL Developer tutorial that is available online at:
SYSTOOLS
http://st-curriculum.oracle.com/tutorial/SQLDeveloper/index.htm
5. Preview and experiment with the available links and demonstrations in the tutorial as needed,
especially the Creating a Database Connection and Accessing Data links.
Creating and Using the New SQL Developer Database Connections
6. Start SQL Developer.
7. Create a database connection to SH using the following information:
a. Connection Name: sh_connection
b. Username: sh
c. Password: sh
d. Hostname: localhost
e. Port: 1521
f. SID: orcl
SYSTOOLS
8. Test the new connection. If the Status is Success, connect to the database using this new
connection.
a. Double-click the sh_connection icon on the Connections tabbed page.
b. Click the Test button in the New/Select Database Connection window. If the status is
Success, click the Connect button.
9. Create a new database connection named hr_connection.
a. Right-click the sh_connection connection in the Object Navigation tree, and select the
Properties menu option.
b. Enter hr_connection as the connection name and hr as the username and password,
and click Save. This creates the new connection.
c. Repeat step 8 to test the new hr_connection connection.
SYSTOOLS
11. Repeat step 9 to create and test a new database connection named sys_connection. Enter
sys as the database connection username, oracle as the password, and SYSDBA as the role.
Browsing the HR, SH, and OE Schema Tables
12. Browse the structure of the EMPLOYEES table.
a. Expand the hr_connection connection by clicking the plus symbol next to it.
b. Expand the Tables icon by clicking the plus symbol next to it.
c. Display the structure of the EMPLOYEES table.
13. Browse the EMPLOYEES table and display its data.
14. Use the SQL worksheet to select the last names and salaries of all employees whose annual
income is greater than $10,000. Use both the Execute Statement (F9) and the Run Script (F5)
icons to execute the SELECT statement. Review the results of both methods of executing the
SELECT statements on the appropriate tabs.
SYSTOOLS
Note: Take a few minutes to familiarize yourself with the data, or consult “Appendix B, Table
Descriptions,” which provides the description and data for all tables in the HR, SH, and OE
schemas that you will use in this course.
15. Create and execute a simple anonymous block that outputs “Hello World.”
a. Enable SET SERVEROUTPUT ON to display the output of the DBMS_OUTPUT package
statements.
b. Use the SQL worksheet area to enter the code for your anonymous block.
c. Click the Run Script icon (F5) to run the anonymous block.
16. Browse the structure of the SALES table in the SH Schema connection and display its data.
a. Double-click the sh_connection connection.
b. Expand the Tables icon by clicking the plus symbol next to it.
c. Display the structure of the SALES table.
d. Browse the SALES table and display its data.
SYSTOOLS
17. Browse the structure of the ORDERS table in the OE Schema and display its data.
a. Double-click the oe_connection connection.
b. Expand the Tables icon by clicking the plus symbol next to it.
c. Display the structure of the ORDERS table.
d. Browse the ORDERS table and display its data.
Accessing the Oracle Database 11g Release 1 Online Documentation Library
18. Access the Oracle Database 11g Release documentation Web page at:
http://www.oracle.com/pls/db111/homepage
19. Bookmark the page for easier future access.
20. Display the complete list of books available for Oracle Database 11g, Release 1.
SYSTOOLS
needed:
a. Advanced Application Developer’s Guide
b. New Features Guide
c. PL/SQL Language Reference
d. Oracle Database Reference
e. Oracle Database Concepts
f. SQL Developer User’s Guide
g. SQL Language Reference Guide
h. SQL*Plus User’s Guide and Reference
SYSTOOLS
SYSTOOLS
SYSTOOLS
Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Objectives
SYSTOOLS
After completing this lesson, you should be able to do the
following:
• Describe PL/SQL basics
• List restrictions on calling functions from SQL expressions
• Identify how explicit cursors are processed
• Handle exceptions
• Use the raise_application_error procedure
• Manage dependencies
• Use Oracle-supplied packages
SYSTOOLS
2-2 Copyright © 2008, Oracle. All rights reserved.
Objectives
PL/SQL supports various programming constructs. This lesson reviews the basic concept of PL/SQL
programming. This lesson also reviews how to:
• Create subprograms
• Use cursors
SYSTOOLS
• Handle exceptions
• Identify predefined Oracle server errors
• Manage dependencies
A quiz at the end of the lesson will assess your knowledge of PL/SQL.
Note: The quiz is optional. Solutions to the quiz are provided in Appendix A.
•
•
SYSTOOLS
Describing PL/SQL basics
Listing restrictions on calling functions from SQL expressions
• Reviewing PL/SQL packages
• Identifying how explicit cursors are processed
• Handling exceptions
• Using the raise_application_error procedure
• Managing dependencies
• Using Oracle-supplied packages
SYSTOOLS
2-3 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS <header>
DECLARE IS|AS
BEGIN BEGIN
EXCEPTION EXCEPTION
END; END;
SYSTOOLS
Anonymous
PL/SQL block
Stored
program unit
SYSTOOLS
is a function, procedure, or a package, and contains the optional argument list and their modes. A
stored program unit also has the other sections mentioned for the anonymous PL/SQL block.
However, a stored program unit does not have an optional DECLARE section, but it does contain an
IS | AS section that is mandatory and acts the same as the DECLARE section in an anonymous
block.
Every PL/SQL construct is made from one or more blocks. These blocks can be entirely separate or
nested within one another. Therefore, one block can represent a small part of another block, which in
turn can be part of the whole unit of code.
SYSTOOLS
Advantages of proper naming conventions:
• Easier to read
• Understandable
• Gives information about the functionality
• Easier to debug
• Ensures consistency
• Can improve performance
SYSTOOLS
2-5 Copyright © 2008, Oracle. All rights reserved.
Naming Conventions
A proper naming convention makes the code easier to read and more understandable. It helps you
understand the functionality of the identifier. If the code is written using proper naming conventions,
you can easily find an error and rectify it. Most importantly, it ensures consistency among the code
written by different developers.
SYSTOOLS
The following table shows the naming conventions followed in this course:
SYSTOOLS
A procedure is:
• A named PL/SQL block that performs a sequence of actions
and optionally returns a value or values
• Stored in the database as a schema object
• Used to promote reusability and maintainability
SYSTOOLS
[local_variable_declarations; …]
BEGIN
-- actions;
END [procedure_name];
Procedures
A procedure is a named PL/SQL block that can accept parameters (sometimes referred to as
arguments). Generally, you use a procedure to perform an action. A procedure is compiled and stored
in the database as a schema object. Procedures promote reusability and maintainability.
Parameters are used to transfer data values to and from the calling environment and the procedure (or
SYSTOOLS
subprogram). Parameters are declared in the subprogram header, after the name and before the
declaration section for local variables.
Parameters are subject to one of the three parameter-passing modes: IN, OUT, or IN OUT.
• An IN parameter passes a constant value from the calling environment into the procedure.
• An OUT parameter passes a value from the procedure to the calling environment.
• An IN OUT parameter passes a value from the calling environment to the procedure and a
possibly different value from the procedure back to the calling environment using the same
parameter.
SYSTOOLS
CREATE OR REPLACE PROCEDURE get_avg_order
(p_cust_id NUMBER, p_cust_last_name VARCHAR2,
p_order_tot NUMBER)
IS
v_cust_ID customers.customer_id%type;
v_cust_name customers.cust_last_name%type;
v_avg_order NUMBER;
BEGIN
SELECT customers.customer_id, customers.cust_last_name,
AVG(orders.order_total)
INTO v_cust_id, v_cust_name, v_avg_order
FROM CUSTOMERS, ORDERS
SYSTOOLS
WHERE customers.customer_id=orders.customer_id
GROUP BY customers.customer_id, customers.cust_last_name;
END;
/
Procedure: Example
This reusable procedure has a parameter with a SELECT statement for getting average order totals
for whatever customer value is passed in.
Note: If a developer drops a procedure, and then re-creates it, all applicable grants to execute the
procedure are gone. Alternatively, the OR REPLACE command removes the old procedure and re-
SYSTOOLS
creates it but leaves all the grants against the said procedure in place. Thus, the OR REPLACE
command is recommended wherever there is an existing procedure, function, or package; not merely
for convenience, but also to protect granted privileges. If you grant object privileges, these privileges
remain after you re-create the subprogram with the OR REPLACE option; otherwise, the privileges
are not preserved.
SYSTOOLS
A function is:
• A named block that must return a value
• Stored in the database as a schema object
• Called as part of an expression or used to provide a
parameter value
SYSTOOLS
BEGIN
-- actions;
RETURN expression;
END [function_name];
Functions
A function is a named PL/SQL block that can accept parameters, be invoked, and return a value. In
general, you use a function to compute a value. Functions and procedures are structured alike. A
function must return a value to the calling environment, whereas a procedure returns zero or more
values to its calling environment. Like a procedure, a function has a header, a declarative section, an
SYSTOOLS
executable section, and an optional exception-handling section. A function must have a RETURN
clause in the header and at least one RETURN statement in the executable section, and must return a
value in each exception handler to avoid the “ORA-06503: PL/SQL: Function returned without
value” error.
Functions can be stored in the database as schema objects for repeated execution. A function that is
stored in the database is referred to as a stored function. Functions can also be created on client-side
applications.
Functions promote reusability and maintainability. When validated, they can be used in any number
of applications. If the processing requirements change, only the function needs to be updated.
A function may also be called as part of a SQL expression or as part of a PL/SQL expression. In the
context of a SQL expression, a function must obey specific rules to control side effects. In a PL/SQL
expression, the function identifier acts like a variable whose value depends on the parameters passed
to it.
SYSTOOLS
• Create the function:
CREATE OR REPLACE FUNCTION get_credit
(v_id customers.customer_id%TYPE) RETURN NUMBER IS
v_credit customers.credit_limit%TYPE := 0;
BEGIN
SELECT credit_limit
INTO v_credit
FROM customers
WHERE customer_id = v_id;
RETURN (v_credit);
END get_credit;
/
value: SYSTOOLS
• Invoke the function as an expression or as a parameter
EXECUTE dbms_output.put_line(get_credit(101))
Function: Example
The get_credit function is created with a single input parameter and returns the credit limit as a
number, as shown in the first code box in the slide. The get_credit function follows the common
programming practice of assigning a returning value to a local variable and uses a single RETURN
statement in the executable section of the code to return the value stored in the local variable. If your
SYSTOOLS
function has an exception section, it may also contain a RETURN statement.
Invoke a function as part of a PL/SQL expression, because the function returns a value to the calling
environment. The second code box uses the SQL*Plus EXECUTE command to call the
DBMS_OUTPUT.PUT_LINE procedure whose argument is the return value from the get_credit
function. In this case, DBMS_OUTPUT.PUT_LINE is invoked first; it calls get_credit to
calculate the credit limit of the customer with ID 101. The credit_limit value returned is
supplied as the value of the DBMS_OUTPUT.PUT_LINE parameter, which then displays the result
(if you have executed SET SERVEROUTPUT ON).
Note: The %TYPE attribute casts the data type to the type defined for the column in the table
identified. You can use the %TYPE attribute as a data type specifier when declaring constants,
variables, fields, and parameters.
A function must always return a value. The example does not return a value if a row is not found for
a given ID. Ideally, create an exception handler to return a value as well.
SYSTOOLS
• Invoke as part of a PL/SQL expression
– Using a host variable to obtain the result:
SYSTOOLS
EXECUTE dbms_output.put_line(get_credit(101))
• Use in a SQL statement (subject to restrictions)
SELECT get_credit(customer_id) FROM customers;
SYSTOOLS
a local variable in an anonymous block.
• As a parameter to another subprogram: The third example in the slide demonstrates this
usage. The get_credit function, with all its arguments, is nested in the parameter required
by the DBMS_OUTPUT.PUT_LINE procedure. This comes from the concept of nesting
functions, as discussed in the Oracle Database 10g: SQL Fundamentals I course.
• As an expression in a SQL statement: The last example shows how a function can be used as a
single-row function in a SQL statement.
Note: The restrictions and guidelines that apply to functions when used in a SQL statement are
discussed in the next few pages.
•
•
SYSTOOLS
Describing PL/SQL basics
Listing restrictions on calling functions from SQL expressions
• Reviewing PL/SQL packages
• Identifying how explicit cursors are processed
• Handling exceptions
• Using the raise_application_error procedure
• Managing dependencies
• Using Oracle-supplied packages
SYSTOOLS
2 - 11 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
from SQL Expressions
• User-defined functions that are callable from SQL
expressions must:
– Be stored in the database
– Accept only IN parameters with valid SQL data types, not
PL/SQL-specific types
– Return valid SQL data types, not PL/SQL-specific types
• When calling functions in SQL statements:
– Parameters must be specified with positional notation
– You must own the function or have the EXECUTE privilege
SYSTOOLS
2 - 12 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
• The functions must return data types that are valid SQL data types. They cannot be PL/SQL-
specific data types such as BOOLEAN, RECORD, or TABLE. The same restriction applies to the
parameters of the function.
The following restrictions apply when calling a function in a SQL statement:
• Parameters must use positional notation. Named notation is not supported.
• You must own or have the EXECUTE privilege on the function.
Other restrictions on a user-defined function include the following:
• It cannot be called from the CHECK constraint clause of a CREATE TABLE or ALTER TABLE
statement.
• It cannot be used to specify a default value for a column.
Note: Only stored functions are callable from SQL statements. Stored procedures cannot be called
unless invoked from a function that meets the preceding requirements.
SYSTOOLS
from SQL Expressions
Functions called from:
• A SELECT statement cannot contain DML statements
• An UPDATE or DELETE statement on a table T cannot query
or contain DML on the same table T
• SQL statements cannot end transactions (that is, cannot
execute COMMIT or ROLLBACK operations)
Note: Calls to subprograms that break these restrictions are
also not allowed in the function.
SYSTOOLS
2 - 13 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
• A SELECT statement or a parallel UPDATE or DELETE statement, the function cannot modify a
database table, unless the modification occurs in an autonomous transaction
• An INSERT... SELECT (but not an INSERT... VALUES), an UPDATE, or a DELETE statement,
the function cannot query or modify a database table that was modified by that statement
• A SELECT, INSERT, UPDATE, or DELETE statement, the function cannot execute directly or
indirectly through another subprogram or through a SQL transaction control statement such as:
- A COMMIT or ROLLBACK statement
- A session control statement (such as SET ROLE)
- A system control statement (such as ALTER SYSTEM)
- Any data definition language (DDL) statements (such as CREATE), because they are
followed by an automatic commit
Note: The function can execute a transaction control statement if the transaction being controlled is
autonomous.
•
•
SYSTOOLS
Describing PL/SQL basics
Listing restrictions on calling functions from SQL expressions
• Reviewing PL/SQL packages
• Identifying how explicit cursors are processed
• Handling exceptions
• Using the raise_application_error procedure
• Managing dependencies
• Using Oracle-supplied packages
SYSTOOLS
2 - 14 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
PL/SQL packages:
• Group logically related components:
– PL/SQL types
– Variables, data structures, and exceptions
– Subprograms: procedures and functions
• Consist of two parts:
– A specification
– A body
• Enable the Oracle server to read multiple objects into
SYSTOOLS
memory simultaneously
SYSTOOLS
A package usually consists of two parts that are stored separately in the database:
• A specification
• A body (optional)
The package itself cannot be called, parameterized, or nested. After writing and compiling, the
contents can be shared with many applications.
When a PL/SQL-packaged construct is referenced for the first time, the whole package is loaded into
memory. However, subsequent access to constructs in the same package does not require disk I/O.
SYSTOOLS
Package
specification variable
Public
Procedure A declaration;
variable
Procedure B definition …
SYSTOOLS
variable
Package BEGIN
body …
END;
SYSTOOLS
• The package body defines its own subprograms and must fully implement the subprograms that
are declared in the specification part. The package body may also define PL/SQL constructs,
such as object types, variables, constants, exceptions, and cursors.
Public components are declared in the package specification. The specification defines a public API
for users of the package features and functionality. That is, public components can be referenced
from any Oracle server environment that is external to the package.
Private components are placed in the package body but not referenced in the specification and can be
referenced only by other constructs within the same package body. Alternatively, private components
can reference the public components of the package.
Note: If a package specification does not contain subprogram declarations, there is no requirement
for a package body.
Syntax: SYSTOOLS
CREATE [OR REPLACE] PACKAGE package_name IS|AS
public type and variable declarations
subprogram specifications
END [package_name];
SYSTOOLS
• All constructs declared in a package specification are visible
to users who are granted privileges on the package.
SYSTOOLS
• The following are the definitions of items in the package syntax:
- package_name specifies a name for the package that must be unique among objects
within the owning schema. Including the package name after the END keyword is optional.
- public type and variable declarations declares public variables, constants,
cursors, exceptions, user-defined types, and subtypes.
- subprogram specifications specifies the public procedure or function
declarations.
Note: The package specification should contain procedure and function signatures terminated by a
semicolon. The signature is every thing above IS|AS keywords. The implementation of a procedure
or function that is declared in a package specification is done in the package body.
Syntax: SYSTOOLS
CREATE [OR REPLACE] PACKAGE BODY package_name IS|AS
private type and variable declarations
subprogram bodies
[BEGIN initialization statements]
END [package_name];
• The OR REPLACE option drops and re-creates the package
body.
• Identifiers defined in the package body are private and not
visible outside the package body.
SYSTOOLS
• All private constructs must be declared before they are
referenced.
• Public constructs are visible to the package body.
SYSTOOLS
variable or subprogram before it can be referenced by other components in the same package
body. It is common to see all private variables and subprograms defined first and the public
subprograms defined last in the package body.
• The package body must complete the implementation for all procedures or functions declared in
the package specification.
The following are the definitions of items in the package body syntax:
• package_name specifies a name for the package that must be the same as its package
specification. Using the package name after the END keyword is optional.
• private type and variable declarations declares private variables, constants,
cursors, exceptions, user-defined types, and subtypes.
• subprogram bodies specifies the full implementation of any private and/or public
procedures or functions.
• [BEGIN initialization statements] is an optional block of initialization code that
executes when the package is first referenced.
•
•
SYSTOOLS
Describing PL/SQL basics
Listing restrictions on calling functions from SQL expressions
• Reviewing PL/SQL packages
• Identifying how explicit cursors are processed
• Handling exceptions
• Using the raise_application_error procedure
• Managing dependencies
• Using Oracle-supplied packages
SYSTOOLS
2 - 19 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• A cursor is a pointer to the private memory area allocated by
the Oracle server.
• There are two types of cursors:
– Implicit cursors: Created and managed internally by the
Oracle server to process SQL statements
– Explicit cursors: Explicitly declared by the programmer
SYSTOOLS
2 - 20 Copyright © 2008, Oracle. All rights reserved.
Cursor
You have already learned that you can include SQL statements that return a single row in a PL/SQL
block. The data retrieved by the SQL statement should be held in variables using the INTO clause.
Where Does Oracle Process SQL Statements?
The Oracle server allocates a private memory area, called the context area, to process SQL
SYSTOOLS
statements. The SQL statement is parsed and processed in this area. The information required for
processing and the information retrieved after processing are stored in this area. Because this area is
internally managed by the Oracle server, you have no control over this area. A cursor is a pointer to
the context area. However, this cursor is an implicit cursor and is automatically managed by the
Oracle server. When the executable block contains a SQL statement, an implicit cursor is created.
There are two types of cursors:
• Implicit cursors: Implicit cursors are created and managed by the Oracle server. You do not
have access to them. The Oracle server creates such a cursor when it executes a SQL statement,
such as SELECT, INSERT, UPDATE, or DELETE.
SYSTOOLS
cases, you can declare cursors explicitly, depending on your business requirements. Such cursors
that are declared by programmers are called explicit cursors. You declare these cursors in the
declarative section of a PL/SQL block. Remember that you can also declare variables and
exceptions in the declarative section.
SYSTOOLS
SYSTOOLS
SYSTOOLS
The following three commands are used to process an explicit
cursor:
• OPEN
• FETCH
• CLOSE
Alternatively, you can also use a cursor FOR loop.
SYSTOOLS
2 - 22 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
• CLOSE
You initialize the cursor with the OPEN command, which recognizes the result set. Then, you execute
the FETCH command repeatedly in a loop until all rows are retrieved. Alternatively, you can use a
BULK COLLECT clause to fetch all rows at once. After the last row is processed, you release the
cursor by using the CLOSE command.
SYSTOOLS
Every explicit cursor has the following attributes:
• cursor_name%FOUND
• cursor_name%ISOPEN
• cursor_name%NOTFOUND
• cursor_name%ROWCOUNT
SYSTOOLS
2 - 23 Copyright © 2008, Oracle. All rights reserved.
Cursor Attributes
When cursor attributes are appended to the cursors, they return useful information about the
execution of the data manipulation language (DML) statement. The following are the four cursor
attributes:
• cursor_name%FOUND: Returns TRUE if the last fetch returned a row; returns NULL before
SYSTOOLS
the first fetch from an OPEN cursor; returns FALSE if the last fetch failed to return a row
• cursor_name%ISOPEN: Returns TRUE if the cursor is open, otherwise returns FALSE
• cursor_name%NOTFOUND: Returns FALSE if the last fetch returned a row; returns NULL
before the first fetch from an OPEN cursor; returns TRUE if the last fetch failed to return a row
• cursor_name%ROWCOUNT: Returns zero before the first fetch; after every fetch, returns the
number of rows fetched so far
Syntax: SYSTOOLS
FOR record_name IN cursor_name LOOP
statement1;
statement2;
. . .
END LOOP;
SYSTOOLS
• The record is implicitly declared.
SYSTOOLS
In the syntax:
record_name Is the name of the implicitly declared record
cursor_name Is a PL/SQL identifier for the previously declared cursor
Guidelines
• Do not declare the record in the loop, because it is declared implicitly.
• Test the cursor attributes during the loop, if required.
• Supply the parameters for a cursor, if required, in parentheses following the cursor name in the
FOR statement.
SYSTOOLS
SET SERVEROUTPUT ON
DECLARE
CURSOR cur_cust IS
SELECT cust_first_name, credit_limit
FROM customers
WHERE credit_limit > 4000;
BEGIN
FOR v_cust_record IN cur_cust
LOOP
DBMS_OUTPUT.PUT_LINE
( v_cust_record.cust_first_name ||' '||
SYSTOOLS
v_cust_record.credit_limit);
END LOOP;
END;
/
Cursor: Example
The example shows the use of a cursor FOR loop.
cust_record is the record that is implicitly declared. You can access the fetched data with this
implicit record as shown in the slide.
Note: An INTO clause or a FETCH statement is not required because the FETCH INTO is implicit.
SYSTOOLS
The code does not have OPEN and CLOSE statements to open and close the cursor, respectively.
•
•
SYSTOOLS
Describing PL/SQL basics
Listing restrictions on calling functions from SQL expressions
• Reviewing PL/SQL packages
• Identifying how explicit cursors are processed
• Handling exceptions
• Using the raise_application_error procedure
• Managing dependencies
• Using Oracle-supplied packages
SYSTOOLS
2 - 26 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• An exception is an error in PL/SQL that is raised during
program execution.
• An exception can be raised:
– Implicitly by the Oracle server
– Explicitly by the program
• An exception can be handled:
– By trapping it with a handler
– By propagating it to the calling environment
– By trapping and propagating it
SYSTOOLS
2 - 27 Copyright © 2008, Oracle. All rights reserved.
Handling Exceptions
An exception is an error in PL/SQL that is raised during the execution of a block. A block always
terminates when PL/SQL raises an exception, but you can specify an exception handler to perform
final actions before the block ends.
Methods for Raising an Exception
SYSTOOLS
• An Oracle error occurs and the associated exception is raised automatically. For example, if the
error ORA-01403 occurs when no rows are retrieved from the database in a SELECT
statement, PL/SQL raises the NO_DATA_FOUND exception. These errors are converted into
predefined exceptions.
• Depending on the business functionality that your program is implementing, you may have to
explicitly raise an exception by issuing the RAISE statement within the block. The exception
being raised may be either user-defined or predefined.
• There are some non-predefined Oracle errors. These errors are any standard Oracle errors that
are not predefined. You can explicitly declare exceptions and associate them with the
nonpredefined Oracle errors.
Methods for Handling an Exception
The third method in the slide for handling an exception involves trapping and propagating. It is often
very important to be able to handle an exception after propagating it to the invoking environment, by
issuing a simple RAISE statement.
SYSTOOLS
Is the
exception Terminate
trapped? no abruptly.
Exception yes
raised
Execute statements Propagate the
in the EXCEPTION exception.
SYSTOOLS
section.
Terminate
gracefully.
SYSTOOLS
exception does not propagate to the enclosing block or to the calling environment. The PL/SQL
block terminates successfully.
Propagating an Exception
If the exception is raised in the executable section of the block and there is no corresponding
exception handler, the PL/SQL block terminates with failure and the exception is propagated to an
enclosing block or to the calling environment. The calling environment can be any application, such
as SQL*Plus, that invokes the PL/SQL program.
DECLARE
SYSTOOLS
v_lname VARCHAR2(15);
BEGIN
SELECT cust_last_name INTO v_lname FROM customers
WHERE cust_first_name='Ally';
DBMS_OUTPUT.PUT_LINE ('Ally''s last name is : '
||v_lname);
EXCEPTION
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE (' Your select statement
SYSTOOLS
retrieved multiple rows. Consider using a
cursor.');
END;
/
Exceptions: Example
You have written PL/SQL blocks with a declarative section (beginning with the keyword DECLARE)
and an executable section (beginning and ending with the keywords BEGIN and END, respectively).
For exception handling, include another optional section called the EXCEPTION section. This
section begins with the keyword EXCEPTION. If present, this is the last section in a PL/SQL block.
SYSTOOLS
Examine the code in the slide to see the EXCEPTION section.
The output of this code is shown below:
Your select statement retrieved multiple rows. Consider using a
cursor.
PL/SQL procedure successfully completed.
When the exception is raised, the control shifts to the EXCEPTION section and all statements in the
specified EXCEPTION section are executed. The PL/SQL block terminates with normal, successful
completion. Only one exception handler is executed.
Note the SELECT statement in the executable block. That statement requires that a query must return
only one row. If multiple rows are returned, a “too many rows” exception is raised. If no rows are
returned, a “no data found” exception is raised. The block of code in the slide tests for the “too many
rows” exception.
SYSTOOLS
• Reference the predefined name in the exception-handling
routine.
• Sample predefined exceptions:
– NO_DATA_FOUND
– TOO_MANY_ROWS
– INVALID_CURSOR
– ZERO_DIVIDE
– DUP_VAL_ON_INDEX
SYSTOOLS
2 - 30 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
Number
SYSTOOLS
INVALID_CURSOR
INVALID_NUMBER
ORA-01001
ORA-01722
Illegal cursor operation occurred.
Conversion of character string to
number failed.
LOGIN_DENIED ORA-01017 Logging on to the Oracle server with
an invalid username or password.
NO_DATA_FOUND ORA-01403 Single-row SELECT returned no data.
SYSTOOLS
cursor variable involved in an
assignment have incompatible return
types.
SYSTOOLS
Error
Number
STORAGE_ERROR ORA-06500 PL/SQL ran out of memory or memory is
corrupted.
SUBSCRIPT_BEYOND_COUNT ORA-06533 Referenced a nested table or varray
element by using an index number larger
than the number of elements in the
collection.
SUBSCRIPT_OUTSIDE_LIMIT ORA-06532 Referenced a nested table or varray
element by using an index number that is
outside the legal range (for example –1).
SYS_INVALID_ROWID ORA-01410 The conversion of a character string into
a universal ROWID failed because the
SYSTOOLS
character string did not represent a valid
ROWID.
TIMEOUT_ON_RESOURCE ORA-00051 Time-out occurred while the Oracle
server was waiting for a resource.
TOO_MANY_ROWS ORA-01422 Single-row SELECT returned more than
one row.
VALUE_ERROR ORA-06502 Arithmetic, conversion, truncation, or
size-constraint error occurred.
ZERO_DIVIDE ORA-01476 Attempted to divide by zero.
SYSTOOLS
SYSTOOLS
Server Errors
SYSTOOLS
exception EXCEPTION_INIT exception
SYSTOOLS
You can trap a nonpredefined Oracle server error by declaring it first. The declared exception is
raised implicitly. In PL/SQL, PRAGMA EXCEPTION_INIT instructs the compiler to associate an
exception name with an Oracle error number. This allows you to refer to any internal exception by
name and to write a specific handler for it.
Note: PRAGMA (also called pseudoinstructions) is the keyword that signifies that the statement is a
compiler directive, which is not processed when the PL/SQL block is executed. Rather, it directs the
PL/SQL compiler to interpret all occurrences of the exception name within the block as the
associated Oracle server error number.
SYSTOOLS
Declare Raise Reference
SYSTOOLS
exception the exception by exception
using the RAISE
statement
SYSTOOLS
number exists. If it does not, you may have to raise the user-defined exception. PL/SQL exceptions
must be:
• Declared in the declarative section of a PL/SQL block
• Raised explicitly with RAISE statements
• Handled in the EXCEPTION section
•
•
SYSTOOLS
Describing PL/SQL basics
Listing restrictions on calling functions from SQL expressions
• Reviewing PL/SQL packages
• Identifying how explicit cursors are processed
• Handling exceptions
• Using the raise_application_error procedure
• Managing dependencies
• Using Oracle-supplied packages
SYSTOOLS
2 - 35 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
Procedure
Syntax:
raise_application_error (error_number,
message[, {TRUE | FALSE}]);
SYSTOOLS
2 - 36 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
In the syntax:
error_number Is a user-specified number for the exception between –20,000
and –20,999 (this is not an Oracle-defined exception number).
TRUE | FALSE Is an optional Boolean parameter. (If TRUE, the error is placed
on the stack of previous errors. If FALSE, the default, the error
replaces all previous errors.)
SYSTOOLS
Procedure
• Is used in two places:
– Executable section
– Exception section
• Returns error conditions to the user in a manner consistent
with other Oracle server errors
SYSTOOLS
2 - 37 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
•
•
SYSTOOLS
Describing PL/SQL basics
Listing restrictions on calling functions from SQL expressions
• Reviewing PL/SQL packages
• Identifying how explicit cursors are processed
• Handling exceptions
• Using the raise_application_error procedure
• Managing dependencies
• Using Oracle-supplied packages
SYSTOOLS
2 - 38 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
Dependent objects Referenced objects
Table Function
View Package specification
Database trigger Procedure
Procedure Sequence
Function Synonym
Package body Table
SYSTOOLS
Package specification
User-defined object
and collection types
View
User-defined object
and collection types
Dependencies
Some objects reference other objects as part of their definitions. For example, a stored procedure
could contain a SELECT statement that selects columns from a table. For this reason, the stored
procedure is called a dependent object, whereas the table is called a referenced object.
Dependency Issues
SYSTOOLS
If you alter the definition of a referenced object, dependent objects may or may not continue to work
properly. For example, if the table definition is changed, a procedure may or may not continue to
work without an error.
The Oracle server automatically records dependencies among objects. To manage dependencies, all
schema objects have a status (valid or invalid) that is recorded in the data dictionary, and you can
view the status in the USER_OBJECTS data dictionary view.
Status Significance
VALID The schema object was compiled and can be immediately used when referenced.
INVALID The schema object must be compiled before it can be used.
SYSTOOLS View or
Procedure procedure Table
xxxxxxxxxxxxxx
vvvvvvvvvvvvvv
xxxxxxxxxxxxxx Direct Direct
vvvvvvvvvvvvvv
xxxxxxxxxxxxxx
dependency dependency
vvvvvvvvvvvvvv
xxxxxxxxxxxxxx
vvvvvvvvvvvvvv
xxxxxxxxxxxxxx
vvvvvvvvvvvvvv
Referenced
Dependent
SYSTOOLS
Dependent Indirect
dependency
Referenced
Dependencies (continued)
A procedure or function can directly or indirectly (through an intermediate view, procedure, function,
or packaged procedure or function) reference the following objects:
• Tables
• Views
SYSTOOLS
• Sequences
• Procedures
• Functions
• Packaged procedures or functions
SYSTOOLS
1. Run the utldtree.sql script to create the objects that
enable you to display the direct and indirect dependencies.
2. Execute the DEPTREE_FILL procedure:
EXECUTE deptree_fill('TABLE','OE','CUSTOMERS')
SYSTOOLS
2 - 41 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
$ORACLE_HOME/rdbms/admin folder.
2. Populate the DEPTREE_TEMPTAB table with information for a particular referenced object by
invoking the DEPTREE_FILL procedure. There are three parameters for this procedure:
object_type Type of the referenced object
object_owner Schema of the referenced object
object_name Name of the referenced object
•
•
SYSTOOLS
Describing PL/SQL basics
Listing restrictions on calling functions from SQL expressions
• Reviewing PL/SQL packages
• Identifying how explicit cursors are processed
• Handling exceptions
• Using the raise_application_error procedure
• Managing dependencies
• Using Oracle-supplied packages
SYSTOOLS
2 - 42 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
Oracle-supplied packages:
• Are provided with the Oracle server
• Extend the functionality of the database
• Enable access to certain SQL features that are normally
restricted for PL/SQL
For example, the DBMS_OUTPUT package was originally
designed to debug PL/SQL programs.
SYSTOOLS
2 - 43 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
may simply want to use these packages as ideas when you create your own stored procedures.
Most of the standard packages are created by running catproc.sql.
SYSTOOLS
Here is an abbreviated list of some Oracle-supplied packages:
• DBMS_ALERT
• DBMS_LOCK
• DBMS_SESSION
• DBMS_OUTPUT
• HTP
• UTL_FILE
• UTL_MAIL
SYSTOOLS
• DBMS_SCHEDULER
SYSTOOLS
The following is a brief description of some listed packages:
• The DBMS_ALERT package supports asynchronous notification of database events. Messages or
alerts are sent on a COMMIT command.
• The DBMS_LOCK package is used to request, convert, and release locks through Oracle Lock
Management services.
• The DBMS_SESSION package enables programmatic use of the ALTER SESSION SQL
statement and other session-level commands.
• The DBMS_OUTPUT package provides debugging and buffering of text data.
• The HTP package writes HTML-tagged data into database buffers.
• The UTL_FILE package enables reading and writing of operating system text files.
• The UTL_MAIL package enables composing and sending of email messages.
• The DBMS_SCHEDULER package enables scheduling and automated execution of PL/SQL
blocks, stored procedures, and external procedures or executables.
SYSTOOLS
The DBMS_OUTPUT package enables you to send messages
from stored subprograms and triggers.
• PUT and PUT_LINE place text in the buffer.
• GET_LINE and GET_LINES read the buffer.
• Use SET SERVEROUTPUT ON to display messages in
SQL*Plus. (The default is OFF.)
PUT
SYSTOOLS
NEW_LINE
Output PUT_LINE
SET SERVEROUT ON [SIZE n]
EXEC proc GET_LINE
GET_LINES Buffer
DBMS_OUTPUT Package
The DBMS_OUTPUT package sends textual messages from any PL/SQL block into a buffer in the
database. The procedures provided by the package include:
• PUT to append text from the procedure to the current line of the line output buffer
• NEW_LINE to place an end-of-line marker in the output buffer
SYSTOOLS
• PUT_LINE to combine the action of PUT and NEW_LINE; to trim leading spaces
• GET_LINE to retrieve the current line from the buffer into a procedure variable
• GET_LINES to retrieve an array of lines into a procedure-array variable
• ENABLE/DISABLE to enable or disable calls to the DBMS_OUTPUT procedures
SYSTOOLS
The UTL_FILE package extends PL/SQL programs to read
and write operating system text files.
• It provides a restricted version of operating system stream
file I/O for text files.
• It can access files in operating system directories defined by
a CREATE DIRECTORY statement.
CREATE DIRECTORY
my_dir AS '/dir'
SYSTOOLS
EXEC proc
UTL_FILE O/S file
UTL_FILE Package
The Oracle-supplied UTL_FILE package is used to access text files in the operating system of the
database server. The database provides read and write access to specific operating system directories
by using:
• A CREATE DIRECTORY statement that associates an alias with an operating system directory.
SYSTOOLS
The database directory alias can be granted the READ and WRITE privileges to control the type
of access to files in the operating system. For example:
CREATE DIRECTORY my_dir AS '/temp/my_files';
GRANT READ, WRITE ON DIRECTORY my_dir TO public;
This approach of using the directory alias created by the CREATE DIRECTORY statement does not
require the database to be restarted. The operating system directories specified should be accessible
to and on the same machine as the database server processes. The path (directory) names may be
case-sensitive for some operating systems.
Note: The DBMS_LOB package can be used to read binary files on the operating system.
SYSTOOLS
In this lesson, you should have learned how to:
• Identify a PL/SQL block
• Create subprograms
• List restrictions on calling functions from SQL expressions
• Use cursors
• Handle exceptions
• Use the raise_application_error procedure
• Identify Oracle-supplied packages
SYSTOOLS
2 - 47 Copyright © 2008, Oracle. All rights reserved.
Summary
This lesson reviewed some basic PL/SQL concepts, such as:
• PL/SQL block structure
• Subprograms
• Cursors
SYSTOOLS
• Exceptions
• Oracle-supplied packages
The quiz on the following pages is designed to test and review your PL/SQL knowledge. This
knowledge is necessary as a baseline for the subsequent chapters to build upon.
SYSTOOLS
This practice covers the review of the following topics:
• PL/SQL basics
• Cursor basics
• Exceptions
• Dependencies
SYSTOOLS
2 - 48 Copyright © 2008, Oracle. All rights reserved.
Practice 2: Overview
In this practice, you test and review your PL/SQL knowledge. This knowledge is necessary as a base
line for the subsequent chapters to build upon.
For answers to the questions in this practice, see Appendix A, “Practice Solutions.”
SYSTOOLS
SYSTOOLS
PL/SQL Basics
1. Which are the four key areas of the basic PL/SQL block? What happens in each area?
4. What are the different modes for parameters and what does each mode do?
SYSTOOLS
6. Which are the two main components of a PL/SQL package?
7. How does the syntax of a SELECT statement used within a PL/SQL block differ from a
SELECT statement issued in SQL*Plus?
8. What is a record?
SYSTOOLS
9. What is an index by table?
SYSTOOLS
13. Where do you define an explicit cursor?
16. What does the FOR UPDATE clause do within a cursor definition?
SYSTOOLS
17. Which command opens an explicit cursor?
19. Name five implicit actions that a cursor FOR loop provides.
SYSTOOLS
SYSTOOLS
happens to this exception?
23. What syntax do you use in the exception handler area of a subprogram?
SYSTOOLS
26. To associate an exception identifier with an Oracle error code, what pragma would you use and
where?
SYSTOOLS
SYSTOOLS
31. Which are the two statuses that a schema object can have and where are they recorded?
32. The Oracle server automatically recompiles invalid procedures when they are called from the
same ______. To avoid compile problems with remote database calls, you can use the
________ model instead of the timestamp model.
34. What script would you run to create the deptree and ideptree views?
SYSTOOLS
35. What does the deptree_fill procedure do and what are the arguments that you need to
provide?
Oracle-Supplied Packages
36. What does the dbms_output package do?
37. How do you write “This procedure works.” from within a PL/SQL program by using
dbms_output?
38. What does dbms_sql do and how does this compare with Native Dynamic SQL?
SYSTOOLS
SYSTOOLS
Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Objectives
SYSTOOLS
After completing this lesson, you should be able to do the
following:
• Identify guidelines for cursor design
• Use cursor variables
• Create subtypes based on the existing types for an
application
SYSTOOLS
3-2 Copyright © 2008, Oracle. All rights reserved.
Objectives
This lesson discusses several concepts that apply to the designing of PL/SQL program units.
This lesson explains how to:
• Design and use cursor variables
• Describe the predefined data types
SYSTOOLS
• Create subtypes based on existing data types for an application
SYSTOOLS
• Identifying guidelines for cursor design
• Using cursor variables
• Creating subtypes based on existing types
SYSTOOLS
3-3 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
Fetch into a record when fetching from a cursor.
DECLARE
CURSOR cur_cust IS
SELECT customer_id, cust_last_name, cust_email
FROM customers
WHERE credit_limit = 1200;
v_cust_record cur_cust%ROWTYPE;
BEGIN
SYSTOOLS
OPEN cur_cust;
LOOP
FETCH cur_cust INTO v_cust_record;
...
SYSTOOLS
SYSTOOLS
Create cursors with parameters.
CREATE OR REPLACE PROCEDURE cust_pack
(p_crd_limit_in NUMBER, p_acct_mgr_in NUMBER)
IS
v_credit_limit NUMBER := 1500;
CURSOR cur_cust
(p_crd_limit NUMBER, p_acct_mgr NUMBER)
IS
SELECT customer_id, cust_last_name, cust_email
FROM customers
WHERE credit_limit = p_crd_limit
AND account_mgr_id = p_acct_mgr;
BEGIN
OPEN cur_cust(p_crd_limit_in, p_acct_mgr_in);
SYSTOOLS
...
CLOSE cur_cust;
...
OPEN cur_cust(v_credit_limit, 145);
...
END;
SYSTOOLS
Additionally, parameters help avoid scoping problems, because the result set for the cursor is not
tied to a specific variable in a program. You can define a cursor at a higher level and use it in
any subblock with variables defined in the local block.
SYSTOOLS
Reference implicit cursor attributes immediately after
the SQL statement executes.
BEGIN
UPDATE customers
SET credit_limit = p_credit_limit
WHERE customer_id = p_cust_id;
get_avg_order(p_cust_id); -- procedure call
SYSTOOLS
IF SQL%NOTFOUND THEN
...
SYSTOOLS
executes ensures that you are dealing with the result of the correct SQL statement.
In the example in the slide, you cannot rely on the value of SQL%NOTFOUND for the UPDATE
statement, because it is likely to be overwritten by the value of another SQL statement in the
get_avg_order procedure. To ensure accuracy, the cursor attribute function
SQL%NOTFOUND needs to be called immediately after the data manipulation language (DML)
statement:
DECLARE
v_flag BOOLEAN;
BEGIN
UPDATE customers
SET credit_limit = p_credit_limit
WHERE customer_id = p_cust_id;
v_flag := SQL%NOTFOUND
get_avg_order(p_cust_id); -- procedure call
IF v_flag THEN
...
Oracle Database 11g: Advanced PL/SQL 3 - 6
Guidelines for Cursor Design
SYSTOOLS
Simplify coding with cursor FOR loops.
CREATE OR REPLACE PROCEDURE cust_pack
(p_crd_limit_in NUMBER, p_acct_mgr_in NUMBER)
IS
v_credit_limit NUMBER := 1500;
CURSOR cur_cust
(p_crd_limit NUMBER, p_acct_mgr NUMBER)
IS
SELECT customer_id, cust_last_name, cust_email
FROM customers
WHERE credit_limit = p_crd_limit
AND account_mgr_id = p_acct_mgr;
BEGIN
FOR cur_rec IN cur_cust (p_crd_limit_in, p_acct_mgr_in)
SYSTOOLS
LOOP -- implicit open and fetch
...
END LOOP; -- implicit close
...
END;
SYSTOOLS
record type that matches the cursor definition. After it processes the last row, the cursor is closed
automatically. If you do not use a cursor FOR loop, forgetting to close your cursor results in
increased memory usage.
SYSTOOLS
• Close a cursor when it is no longer needed.
• Use column aliases in cursors for calculated columns
fetched into records declared with %ROWTYPE.
CREATE OR REPLACE PROCEDURE cust_list
IS
CURSOR cur_cust IS
SELECT customer_id, cust_last_name, credit_limit*1.1
FROM customers;
cust_record cur_cust%ROWTYPE;
BEGIN Use col. alias
OPEN cur_cust;
LOOP
FETCH cur_cust INTO cust_record;
SYSTOOLS
DBMS_OUTPUT.PUT_LINE('Customer ' ||
cust_record.cust_last_name || ' wants credit '
|| cust_record.(credit_limit * 1.1));
EXIT WHEN cur_cust%NOTFOUND;
END LOOP;
...
SYSTOOLS
releases memory. Ending the transaction by committing or rolling back releases the locks.
Along with a FOR UPDATE clause, you can also use a WHERE CURRENT OF clause with
the DML statements inside the FOR loop. This automatically performs a DML transaction
for the current row in the cursor’s result set, thereby improving performance.
Note: It is a good programming practice to explicitly close your cursors. Leaving cursors
open can generate an exception, because the number of cursors allowed to remain open
within a session is limited.
• Make sure that you use column aliases in your cursor for calculated columns that you fetch
into a record declared with a %ROWTYPE declaration. You would also need column aliases
if you want to reference the calculated column in your program.
The code in the slide does not compile successfully, because it lacks a column alias for the
calculation credit_limit*1.1. After you give it an alias, use the same alias later in the
code to make a reference to the calculation.
SYSTOOLS
• Identifying guidelines for cursor design
• Using cursor variables
• Creating subtypes based on existing types
SYSTOOLS
3-9 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Memory
SYSTOOLS
1 Southlake, Texas 1400
REF
2 San Francisco 1500 CURSOR
3 New Jersey 1600 memory
locator
4 Seattle, Washington 1700
5 Toronto 1800
SYSTOOLS
3 - 10 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
REF CURSOR data type, where REF stands for reference, and CURSOR stands for the class of
the object.
Using Cursor Variables
To execute a multiple-row query, the Oracle server opens a work area called a “cursor” to store
the processing information. To access the information, you either explicitly name the work area,
or you use a cursor variable that points to the work area. Whereas a cursor always refers to the
same work area, a cursor variable can refer to different work areas. Therefore, cursors and cursor
variables are not interoperable.
An explicit cursor is static and is associated with one SQL statement. A cursor variable can be
associated with different statements at run time.
Primarily, you use a cursor variable to pass a pointer to query result sets between PL/SQL-stored
subprograms and various clients, such as a Developer Forms application. None of them owns the
result set. They simply share a pointer to the query work area that stores the result set.
SYSTOOLS
SYSTOOLS
cursor variable. result set. variable.
variable.
1 2 3 4
SYSTOOLS
SYSTOOLS
• Strong REF CURSOR:
– Is restrictive
– Specifies a RETURN type
– Associates only with type-compatible queries
– Is less error prone
• Weak REF CURSOR:
– Is nonrestrictive
– Associates with any query
– Is very flexible
SYSTOOLS
3 - 12 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
REF CURSOR types more flexible.
In the following example, the first definition is strong, whereas the second is weak:
DECLARE
TYPE rt_cust IS REF CURSOR RETURN customers%ROWTYPE;
TYPE rt_general_purpose IS REF CURSOR;
...
SYSTOOLS
Define a REF CURSOR type:
TYPE ref_type_name IS REF CURSOR
[RETURN return_type];
• ref_type_name is a type specified in subsequent
declarations.
• return_type represents a record type.
• RETURN keyword indicates a strong cursor.
DECLARE
SYSTOOLS
TYPE rt_cust IS REF CURSOR
RETURN customers%ROWTYPE;
...
SYSTOOLS
where: ref_type_name is a type specified in subsequent declarations.
return_type represents a row in a database table.
The REF keyword indicates that the new type is to be a pointer to the defined type. The
return_type is a record type indicating the types of the select list that are eventually
returned by the cursor variable. The return type must be a record type.
Example
DECLARE
TYPE rt_cust IS REF CURSOR RETURN customers%ROWTYPE;
...
SYSTOOLS
Declare a cursor variable of a cursor type:
cursor_variable_name ref_type_name;
DECLARE
TYPE rt_cust IS REF CURSOR
SYSTOOLS
RETURN customers%ROWTYPE;
cv_cust rt_cust;
SYSTOOLS
Cursor variables follow the same scoping and instantiation rules as all other PL/SQL variables.
In the following example, you declare the cursor variable cv_cust.
Step 1:
DECLARE
TYPE ct_cust IS REF CURSOR RETURN customers%ROWTYPE;
cv_cust rt_cust;
Options:
SYSTOOLS Return Type
SYSTOOLS
3 - 15 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
cv_cust rt_cust; --cursor variable
• Specify a user-defined record in the RETURN clause:
DECLARE
TYPE cust_rec_typ IS RECORD
(custno NUMBER(4),
custname VARCHAR2(10),
credit NUMBER(7,2));
TYPE rt_cust IS REF CURSOR RETURN cust_rec_typ;
cv_cust rt_cust;
• Declare a cursor variable as the formal parameter of a stored procedure or function:
DECLARE
TYPE rt_cust IS REF CURSOR RETURN customers%ROWTYPE;
PROCEDURE use_cust_cur_var(cv_cust IN OUT rt_cust)
IS ...
SYSTOOLS
• Associate a cursor variable with a multiple-row SELECT
statement.
• Execute the query.
• Identify the result set:
OPEN cursor_variable_name
FOR select_statement;
SYSTOOLS
– select_statement is the SQL SELECT statement.
SYSTOOLS
several alternatives in an IF THEN ELSE statement. When called, the procedure opens the
cursor variable for the chosen query.
CREATE OR REPLACE PACKAGE cust_data
IS
TYPE rt_cust IS REF CURSOR RETURN customers%ROWTYPE;
PROCEDURE open_cust_cur_var(cv_cust IN OUT rt_cust,
p_your_choice IN NUMBER);
END cust_data;
/
SYSTOOLS
PROCEDURE open_cust_cur_var(cv_cust IN OUT rt_cust,
p_your_choice IN NUMBER)
IS
BEGIN
IF p_your_choice = 1 THEN
OPEN cv_cust FOR SELECT * FROM customers;
ELSIF p_your_choice = 2 THEN
OPEN cv_cust FOR SELECT * FROM customers
WHERE credit_limit > 3000;
ELSIF p_your_choice = 3 THEN
...
END IF;
END open_cust_cur_var;
END cust_data;
/
SYSTOOLS
SYSTOOLS
SYSTOOLS
• Retrieve rows from the result set one at a time.
FETCH cursor_variable_name
INTO variable_name1
[,variable_name2,. . .]
| record_name;
SYSTOOLS
3 - 18 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
a mismatch in number or type, the error occurs at compile time for strongly typed cursor
variables and at run time for weakly typed cursor variables.
Note: When you declare a cursor variable as the formal parameter of a subprogram that fetches
from a cursor variable, you must specify the IN (or IN OUT) mode. If the subprogram also
opens the cursor variable, you must specify the IN OUT mode.
SYSTOOLS
• Disable a cursor variable.
• The result set is undefined.
CLOSE cursor_variable_name;
SYSTOOLS
3 - 19 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
...
LOOP
FETCH cv_cust INTO cust_rec;
EXIT WHEN cv_cust%NOTFOUND;
...
END LOOP;
CLOSE cv_cust;
...
SYSTOOLS
You can pass query result sets among PL/SQL-stored
subprograms and various clients.
Pointer
Access by a host variable
to the
result on the client side
SYSTOOLS
set
SYSTOOLS
refer to the same work area. This might be useful in Oracle Forms, for instance, when you want
to populate a multiple-block form.
Example
Using SQL*Plus, define a host variable with a data type of REFCURSOR to hold the query
results generated from a REF CURSOR in a stored subprogram. Use the SQL*Plus PRINT
command to view the host variable results. Optionally, you can set the SQL*Plus command SET
AUTOPRINT ON to display the query results automatically.
SQL> VARIABLE cv REFCURSOR
Next, create a subprogram that uses a REF CURSOR to pass the cursor variable data back to the
SQL*Plus environment.
Note: You can define a host variable in SQL*Plus or SQL Developer. This slide uses SQL*Plus.
The next slide shows the use of SQL Developer.
SYSTOOLS
SYSTOOLS
3 - 21 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
PROCEDURE get_cust
(p_custid IN NUMBER, p_cv_cust IN OUT rt_cust);
END;
/
SYSTOOLS
PROCEDURE get_cust
(p_custid IN NUMBER, p_cv_cust IN OUT rt_cust)
IS
BEGIN
OPEN p_cv_cust FOR
SELECT customer_id, cust_first_name, credit_limit, cust_email
FROM customers
WHERE customer_id = p_custid;
-- CLOSE p_cv_cust
END;
END;
/
Note that the CLOSE p_cv_cust statement is commented. This is done because, if you close
the REF cursor, it is not accessible from the host variable.
SYSTOOLS
SYSTOOLS
SYSTOOLS
CREATE OR REPLACE PROCEDURE REFCUR
(p_num IN NUMBER)
IS
refcur sys_refcursor; SYS_REFCURSOR is a built-in
empno emp.empno%TYPE; REF CURSOR type that allows
ename emp.ename%TYPE; any result set to be associated
BEGIN with it.
IF p_num = 1 THEN
OPEN refcur FOR Richard
SELECTGreen:
Richard empno, ename FROM emp;
Green:
DBMS_OUTPUT.PUT_LINE('Employee#
Add Name');
Addthis
thisnew
newcontent
contenton
on
DBMS_OUTPUT.PUT_LINE('-----
SYS_REFCURSOR -------');
SYS_REFCURSORfrom from
LOOP David Jacob-Daub
David Jacob-Daub
SYSTOOLS
FETCH refcur INTO empno, ename;
EXIT WHEN refcur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(empno || ' ' || ename);
END LOOP;
ELSE
....
SYSTOOLS
SYS_REFCURSOR can be used to:
• Declare a cursor variable in an Oracle stored procedure or function
• Pass cursors from and to an Oracle stored procedure or function
Note: Strong (restrictive) REF CURSORS require the result set to conform to a declared number
and order of fields with compatible data types, and can also, optionally, return a result set.
CREATE OR REPLACE PROCEDURE REFCUR
(p_num IN NUMBER)
IS
refcur sys_refcursor;
empno emp.empno%TYPE;
ename emp.ename%TYPE;
BEGIN
-- continued on the next page
SYSTOOLS
IF p_num = 1 THEN
OPEN refcur FOR SELECT empno, ename FROM emp;
DBMS_OUTPUT.PUT_LINE('Employee# Name');
DBMS_OUTPUT.PUT_LINE('----- -------');
LOOP
FETCH refcur INTO empno, ename;
EXIT WHEN refcur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(empno || ' ' || ename);
END LOOP;
ELSE
OPEN refcur FOR
SELECT empno, ename
FROM emp WHERE deptno = 30;
DBMS_OUTPUT.PUT_LINE('Employee# Name');
DBMS_OUTPUT.PUT_LINE('----- -------');
LOOP
SYSTOOLS
FETCH refcur INTO empno, ename;
EXIT WHEN refcur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(empno || ' ' || ename);
END LOOP;
END IF;
CLOSE refcur;
END;
/
SYSTOOLS
SYSTOOLS
• You cannot use cursor variables with remote subprograms
on another server.
• You cannot use comparison operators to test cursor
variables.
• You cannot assign a null value to cursor variables.
• You cannot use REF CURSOR types in CREATE TABLE or
VIEW statements.
• Cursors and cursor variables are not interoperable.
SYSTOOLS
3 - 25 Copyright © 2008, Oracle. All rights reserved.
Restrictions
• Remote subprograms on another server cannot accept the values of cursor variables.
Therefore, you cannot use remote procedure calls (RPCs) to pass cursor variables from one
server to another.
• If you pass a host cursor variable to PL/SQL, you cannot fetch from it on the server side
SYSTOOLS
unless you open it in the server on the same server call.
• You cannot use comparison operators to test cursor variables for equality, inequality, or
nullity.
• You cannot assign NULLs to a cursor variable.
• You cannot use the REF CURSOR types to specify column types in a CREATE TABLE or
CREATE VIEW statement. So, database columns cannot store the values of cursor
variables.
• You cannot use a REF CURSOR type to specify the element type of a collection, which
means that the elements in an index by table, nested table, or VARRAY cannot store the
values of cursor variables.
• Cursors and cursor variables are not interoperable, that is, you cannot use one where the
other is expected.
SYSTOOLS
3 - 26 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
passed between programs, no matter where the programs exist.
Cursor variables can reduce network traffic by grouping OPEN FOR statements and sending
them across the network only once. For example, the following PL/SQL block opens two cursor
variables in a single round trip:
/* anonymous PL/SQL block in host environment */
BEGIN
OPEN :cv_cust FOR SELECT * FROM customers;
OPEN :cv_orders FOR SELECT * FROM orders;
END;
This may be useful in Oracle Forms, for instance, when you want to populate a multiple-block
form. When you pass host cursor variables to a PL/SQL block for opening, the query work areas
to which they point remain accessible after the block completes. This enables your OCI or
Pro*C program to use these work areas for ordinary cursor operations.
SYSTOOLS
• Identifying guidelines for cursor design
• Using Cursor Variables
• Creating subtypes based on existing types
SYSTOOLS
3 - 27 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
Scalar Types
BINARY_DOUBLE
BINARY_FLOAT
CHAR
CHARACTER
Composite Types
RECORD
TABLE
VARRAY
BINARY_INTEGER LONG
DEC LONG RAW
DECIMAL NCHAR
DOUBLE PRECISION NVARCHAR2
FLOAT RAW
INT ROWID Reference Types
INTEGER STRING REF CURSOR
NATURAL UROWID REF object_type
NATURALN VARCHAR
NUMBER VARCHAR2
NUMERIC
SYSTOOLS
PLS_INTEGER BOOLEAN
POSITIVE LOB Types
POSITIVEN
DATE BFILE
REAL
INTERVAL BLOB
SIGNTYPE
TIMESTAMP CLOB
SMALLINT
NCLOB
SYSTOOLS
SYSTOOLS
A subtype is a subset of an existing data type that may place a
constraint on its base type.
PL/SQL-predefined
Subtype
SYSTOOLS
Scalar
data type
User-defined
Subtypes: Overview
A subtype is a data type based on an existing data type. It does not define a new data type;
instead, it places a constraint on an existing data type. There are several predefined subsets
specified in the standard package. DECIMAL and INTEGER are subtypes of NUMBER.
CHARACTER is a subtype of CHAR.
SYSTOOLS
Standard Subtypes
BINARY_INTEGER NUMBER VARCHAR2
NATURAL DEC STRING
NATURALN DECIMAL VARCHAR
POSITIVE DOUBLE PRECISION
POSITIVEN FLOAT
SIGNTYPE INTEGER
INT
NUMERIC
REAL
SMALLINT
SYSTOOLS
and positive values, respectively. NATURALN and POSITIVEN prevent the assigning of nulls to
an integer variable. You can use SIGNTYPE to restrict an integer variable to the values –1, 0,
and 1, which is useful in programming tri-state logic.
A constrained subtype is a subset of the values normally specified by the data type on which the
subtype is based. POSITIVE is a constrained subtype of BINARY_INTEGER.
An unconstrained subtype is not a subset of another data type; it is an alias to another data type.
FLOAT is an unconstrained subtype of NUMBER.
Use the subtypes DEC, DECIMAL, and NUMERIC to declare fixed-point numbers with a
maximum precision of 38 decimal digits.
Use the subtypes DOUBLE PRECISION and FLOAT to declare floating-point numbers with a
maximum precision of 126 binary digits, which is roughly equivalent to 38 decimal digits. Or,
use the subtype REAL to declare floating-point numbers with a maximum precision of 63 binary
digits, which is roughly equivalent to 18 decimal digits.
Use the subtypes INTEGER, INT, and SMALLINT to declare integers with a maximum
SYSTOOLS
precision of 38 decimal digits.
You can even create your own user-defined subtypes.
Note: You can use these subtypes for compatibility with ANSI/ISO and IBM types. Currently,
VARCHAR is synonymous with VARCHAR2. However, in future releases of PL/SQL, to
accommodate emerging SQL standards, VARCHAR may become a separate data type with
different comparison semantics. It is a good idea to use VARCHAR2 rather than VARCHAR.
SYSTOOLS
Subtypes:
SYSTOOLS
• Increase reliability
• Provide compatibility with ANSI/ISO and IBM types
• Promote reusability
• Improve readability
– Clarity
– Code self-documents
SYSTOOLS
3 - 31 Copyright © 2008, Oracle. All rights reserved.
Benefits of Subtypes
If your applications require a subset of an existing data type, you can create subtypes. By using
subtypes, you can increase the reliability and improve the readability by indicating the intended
use of constants and variables. Subtypes can increase reliability by detecting the out-of-range
values.
SYSTOOLS
With predefined subtypes, you have compatibility with other data types from other programming
languages.
SYSTOOLS
• Subtypes are defined in the declarative section of a PL/SQL
block.
SYSTOOLS
3 - 32 Copyright © 2008, Oracle. All rights reserved.
Declaring Subtypes
Subtypes are defined in the declarative section of a PL/SQL block, subprogram, or package.
Using the SUBTYPE keyword, you name the subtype and provide the name of the base type.
You can use the %TYPE attribute on the base type to pick up a data type from a database column
or from an existing variable data type. You can also use the %ROWTYPE attribute.
SYSTOOLS
Examples
CREATE OR REPLACE PACKAGE mytypes
IS
SUBTYPE Counter IS INTEGER; -- based on INTEGER type
TYPE typ_TimeRec IS RECORD (minutes INTEGER, hours
INTEGER);
SUBTYPE Time IS typ_TimeRec; -- based on RECORD type
SUBTYPE ID_Num IS customers.customer_id%TYPE;
CURSOR cur_cust IS SELECT * FROM customers;
SUBTYPE CustFile IS cur_cust%ROWTYPE; -- based on cursor
END mytypes;
/
SYSTOOLS
• Define a variable that uses the subtype in the declarative
section.
identifier_name subtype_name;
identifier_name subtype_name(size);
SYSTOOLS
the subtype.
Using Subtypes
After a subtype is declared, you can assign an identifier for that subtype. Subtypes can increase
reliability by detecting out-of-range values.
DECLARE
v_rows mytypes.Counter; --use package subtype dfn
v_customers mytypes.Counter;
SYSTOOLS
v_start_time mytypes.Time;
SUBTYPE Accumulator IS NUMBER;
v_total Accumulator(4,2);
SUBTYPE Scale IS NUMBER(1,0); -- constrained subtype
v_x_axis Scale; -- magnitude range is -9 .. 9
BEGIN
v_rows := 1;
v_start_time.minutes := 15;
v_start_time.hours := 03;
dbms_output.put_line('Start time is: '||
v_start_time.hours|| ':' || v_start_time.minutes);
END;
/
SYSTOOLS
An unconstrained subtype is interchangeable with its base type.
DECLARE
SUBTYPE Accumulator IS NUMBER (4,2);
v_amount accumulator;
v_total NUMBER;
BEGIN
v_amount := 99.99;
v_total := 100.00;
dbms_output.put_line('Amount is: ' || v_amount);
dbms_output.put_line('Total is: ' || v_total);
v_total := v_amount;
dbms_output.put_line('This works too: ' ||
v_total);
SYSTOOLS
-- v_amount := v_amount + 1; Will show value error
END;
/
Subtype Compatibility
Some applications require constraining subtypes to a size specification for scientific purposes.
The example in the slide shows that if you exceed the size of your subtype, you receive an error.
An unconstrained subtype is interchangeable with its base type. Different subtypes are
interchangeable if they have the same base type. Different subtypes are also interchangeable if
SYSTOOLS
their base types are in the same data type family.
DECLARE
v_rows mytypes.Counter; v_customers mytypes.Counter;
SUBTYPE Accumulator IS NUMBER (6,2);
v_total NUMBER;
BEGIN
SELECT COUNT(*) INTO v_customers FROM customers;
SELECT COUNT(*) INTO v_rows FROM orders;
v_total := v_customers + v_rows;
DBMS_OUTPUT.PUT_LINE('Total rows from 2 tables: '||
v_total);
EXCEPTION
WHEN value_error THEN
DBMS_OUTPUT.PUT_LINE('Error in data type.');
END;
SYSTOOLS
In this lesson, you should have learned how to:
• Use guidelines for cursor design
• Declare, define, and use cursor variables
• Use subtypes as data types
SYSTOOLS
3 - 35 Copyright © 2008, Oracle. All rights reserved.
Summary
• Use the guidelines for designing the cursors.
• Take advantage of the features of cursor variables and pass pointers to result sets to
different applications.
• You can use subtypes to organize and strongly type data types for an application.
SYSTOOLS
SYSTOOLS
This practice covers the following topics:
• Determining the output of a PL/SQL block
• Improving the performance of a PL/SQL block
• Implementing subtypes
• Using cursor variables
SYSTOOLS
3 - 36 Copyright © 2008, Oracle. All rights reserved.
Practice 3: Overview
In this practice, you determine the output of a PL/SQL code snippet and modify the snippet to
improve performance. Next, you implement subtypes and use cursor variables to pass values to
and from a package.
SYSTOOLS
SYSTOOLS
solution scripts are provided for each question and are located in the /soln folder. Your
instructor will provide you with the exact location of these files. Connect as OE to perform the
steps.
1. Determine the output of the following code snippet in the lab_03_01.sql file.
SET SERVEROUTPUT ON
BEGIN
UPDATE orders SET order_status = order_status;
FOR v_rec IN ( SELECT order_id FROM orders )
LOOP
IF SQL%ISOPEN THEN
DBMS_OUTPUT.PUT_LINE('TRUE – ' || SQL%ROWCOUNT);
ELSE
DBMS_OUTPUT.PUT_LINE('FALSE – ' || SQL%ROWCOUNT);
END IF;
END LOOP;
END;
SYSTOOLS
/
2. Modify the following code snippet in the lab_03_02.sql file to make better use of the
FOR UPDATE clause and improve the performance of the program.
DECLARE
CURSOR cur_update
IS SELECT * FROM customers
WHERE credit_limit < 5000 FOR UPDATE;
BEGIN
FOR v_rec IN cur_update
LOOP
IF v_rec IS NOT NULL
THEN
UPDATE customers
SET credit_limit = credit_limit + 200
SYSTOOLS
WHERE customer_id = v_rec.customer_id;
END IF;
END LOOP;
END;
/
SYSTOOLS
warranty_period field of the product_information table. Name this package
MY_TYPES. The type needs to hold the month and year for a warranty period.
4. Create a package named SHOW_DETAILS that contains two subroutines. The first
subroutine should show order details for the given order_id. The second subroutine
should show customer details for the given customer_id, including the customer ID, the
first name, phone numbers, credit limit, and email address. Both the subroutines should use
the cursor variable to return the necessary details.
SYSTOOLS
SYSTOOLS
SYSTOOLS
Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
Objectives
SYSTOOLS
• Distinguish between the different types of collections and
when to use them
Objectives
In this lesson, you are introduced to PL/SQL programming using collections.
A collection is an ordered group of elements, all of the same type (for example, phone
numbers for each customer). Each element has a unique subscript that determines its position
in the collection.
SYSTOOLS
Collections work like the set, queue, stack, and hash table data structures found in most third-
generation programming languages. Collections can store instances of an object type and can
also be attributes of an object type. Collections can be passed as parameters. So, you can use
them to move columns of data into and out of database tables, or between client-side
applications and stored subprograms. You can define collection types in a PL/SQL package,
and then use the same types across many applications.
• Understanding collections
• Using associative arrays
• Using nested tables
• Using varrays
• Working with collections
• Programming for collection exceptions
• Summarizing collections
SYSTOOLS
4-3 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
– Nested tables
– Varrays
Understanding Collections
A collection is a group of elements, all of the same type. Each element has a unique subscript
that determines its position in the collection. Collections work like the arrays found in most
third-generation programming languages. They can store instances of an object type and,
conversely, can be attributes of an object type. Collections can also be passed as parameters.
You can use them to move columns of data into and out of database tables, or between client-
SYSTOOLS
side applications and stored subprograms.
Object types are used not only to create object relational tables, but also to define collections.
You can use any of the three categories of collections:
• Associative arrays (known as “index by tables” in previous Oracle releases) are sets of
key-value pairs, where each key is unique and is used to locate a corresponding value in
the array. The key can be an integer or a string.
• Nested tables can have any number of elements.
• A varray is an ordered collection of elements.
Note: Associative arrays indexed by pls_integer are covered in the prerequisite courses—
Oracle Database 11g: Program with PL/SQL and Oracle Database 11g: Develop PL/SQL
Program Units—and are not emphasized in this course.
Associative array
Index by Index by
PLS_INTEGER VARCHAR2
1 2 3 4 5 6 a f i o t w
SYSTOOLS
4-5 Copyright © 2008, Oracle. All rights reserved.
Collection Types
PL/SQL offers three collection types:
Associative Arrays
Associative arrays are sets of key-value pairs, where each key is unique and is used to locate a
corresponding value in the array. The key can be either integer (PLS_INTEGER or
SYSTOOLS
BINARY_INTEGER) or character (VARCHAR2) based. Associative arrays may be sparse.
When you assign a value using a key for the first time, it adds that key to the associative array.
Subsequent assignments using the same key update the same entry. However, it is important to
choose a key that is unique. For example, the key values may come from the primary key of a
database table, from a numeric hash function, or from concatenating strings to form a unique
string value.
Because associative arrays are intended for storing temporary data, you cannot use them with
SQL statements, such as INSERT and SELECT INTO. You can make them persistent for the
life of a database session by declaring the type in a package and assigning the values in a
package body. They are typically populated with a SELECT BULK COLLECT statement
unless they are VARCHAR2 indexed. BULK COLLECT prevents context switching between
the SQL and PL/SQL engines, and is much more efficient on large data sets.
SYSTOOLS
A nested table holds a set of values. In other words, it is a table within a table. Nested tables
are unbounded; that is, the size of the table can increase dynamically. Nested tables are
available in both PL/SQL and the database. Within PL/SQL, nested tables are like one-
dimensional arrays whose size can increase dynamically. Within the database, nested tables
are column types that hold sets of values. The Oracle database stores the rows of a nested table
in no particular order. When you retrieve a nested table from the database into a PL/SQL
variable, the rows are given consecutive subscripts starting at 1. This gives you an array-like
access to individual rows. Nested tables are initially dense, but they can become sparse
through deletions and, therefore, have nonconsecutive subscripts.
Varrays
Variable-size arrays, or varrays, are also collections of homogeneous elements that hold a
fixed number of elements (although you can change the number of elements at run time). They
use sequential numbers as subscripts. You can define equivalent SQL types, thereby allowing
varrays to be stored in database tables. They can be stored and retrieved through SQL, but with
SYSTOOLS
less flexibility than nested tables. You can reference the individual elements for array
operations or manipulate the collection as a whole.
Varrays are always bounded and never sparse. You can specify the maximum size of the
varray in its type definition. Its index has a fixed lower bound of 1 and an extensible upper
bound. A varray can contain a varying number of elements, from zero (when empty) to the
maximum specified in its type definition.
Choosing a PL/SQL Collection Type
If you already have code or business logic that uses another language, you can usually translate
that language’s array and set the types directly to the PL/SQL collection types.
• Arrays in other languages become varrays in PL/SQL.
• Sets and bags in other languages become nested tables in PL/SQL.
• Hash tables and other kinds of unordered lookup tables in other languages become
associative arrays in PL/SQL.
SYSTOOLS
If you are writing original code or designing the business logic from the start, consider the
strengths of each collection type and decide which is appropriate.
Why Use Collections?
Collections offer object-oriented features such as variable-length arrays and nested tables that
provide higher-level ways to organize and access data in the database. Below the object layer,
data is still stored in columns and tables, but you are able to work with the data in terms of the
real-world entities, such as customers and purchase orders, that make the data meaningful.
• Understanding collections
• Using associative arrays
• Using nested tables
• Using varrays
• Working with collections
• Programming for collection exceptions
• Summarizing collections
SYSTOOLS
4-7 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Associative arrays:
• That are indexed by strings can improve performance
• Are pure memory structures that are much faster than
schema-level tables
• Provide significant additional flexibility
Associative arrays
SYSTOOLS
Index by Index by
PLS_INTEGER VARCHAR2
1 2 3 4 5 6 a f i o t w
SYSTOOLS
You can use INDEX BY VARCHAR2 tables (also known as string-indexed arrays). These
tables are optimized for efficiency by implicitly using the B*-tree organization of the values.
The INDEX BY VARCHAR2 table is optimized for efficiency of lookup on a nonnumeric
key, where the notion of sparseness is not applicable. In contrast, the INDEX BY
PLS_INTEGER tables are optimized for compactness of storage on the assumption that the
data is dense.
Note: Associative arrays indexed by PLS INTEGER are covered in the prerequisite courses—
Oracle Database 11g: Program with PL/SQL and Oracle Database 11g: Develop PL/SQL
Program Units—and are not emphasized in this course.
PROCEDURE load_arrays IS
BEGIN
SYSTOOLS
FOR rec IN (SELECT * FROM customers WHERE cust_email IS NOT NULL)
LOOP
-- Load up the array in single pass to database table.
v_by_cust_email (rec.cust_email) := rec;
END LOOP;
END;
...
SYSTOOLS
multiple passes over a significant set of static data, you can instead move it from the database
to a set of collections. Accessing collection-based data is much faster than going through the
SQL engine.
After transferring the data from the database to the collections, you can use string- and integer-
based indexing on those collections to, in essence, mimic the primary key and unique indexes
on the table.
In the REPORT_CREDIT procedure shown in the slide, you may need to determine whether a
customer has adequate credit. The string-indexed collection is loaded with the customer
information in the LOAD_ARRAYS procedure. In the main body of the program, the collection
is traversed to find the credit information. The email name is reported in case more than one
customer has the same last name.
...
BEGIN
load_arrays;
i:= v_by_cust_email.FIRST;
dbms_output.put_line ('For credit amount of: ' || p_credit_limit);
WHILE i IS NOT NULL LOOP
IF v_by_cust_email(i).cust_last_name = p_last_name
AND v_by_cust_email(i).credit_limit > p_credit_limit
THEN dbms_output.put_line ( 'Customer '||
v_by_cust_email(i).cust_last_name || ': ' ||
v_by_cust_email(i).cust_email || ' has credit limit of: ' ||
v_by_cust_email(i).credit_limit);
END IF;
i := v_by_cust_email.NEXT(i);
END LOOP;
END report_credit;
SYSTOOLS
/
SYSTOOLS
SYSTOOLS
CREATE OR REPLACE PROCEDURE report_credit
(p_email customers.cust_last_name%TYPE,
p_credit_limit customers.credit_limit%TYPE)
IS
TYPE typ_name IS TABLE OF customers%ROWTYPE
INDEX BY customers.cust_email%TYPE;
v_by_cust_email typ_name;
i VARCHAR2(30);
PROCEDURE load_arrays IS
BEGIN
FOR rec IN (SELECT * FROM customers
WHERE cust_email IS NOT NULL) LOOP
v_by_cust_email (rec.cust_email) := rec;
END LOOP;
END;
SYSTOOLS
BEGIN
load_arrays;
dbms_output.put_line
('For credit amount of: ' || p_credit_limit);
IF v_by_cust_email(p_email).credit_limit > p_credit_limit
THEN dbms_output.put_line ( 'Customer '||
v_by_cust_email(p_email).cust_last_name ||
': ' || v_by_cust_email(p_email).cust_email ||
' has credit limit of: ' ||
v_by_cust_email(p_email).credit_limit);
END IF;
END report_credit;
/
SYSTOOLS
For credit amount of: 100
Customer Walken: [email protected] has credit limit of:
3700
• Understanding collections
• Using associative arrays
• Using nested tables
• Using varrays
• Working with collections
• Programming for collection exceptions
• Summarizing collections
SYSTOOLS
4 - 12 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
4 - 13 Copyright © 2008, Oracle. All rights reserved.
Nested Tables
A nested table holds a set of values. In other words, it is a table within a table. Nested tables
are unbounded, meaning that the size of the table can increase dynamically. Nested tables are
available in both PL/SQL as well as the database. Within PL/SQL, nested tables are like one-
dimensional arrays whose size can increase dynamically. Within the database, nested tables
are column types that hold sets of values. The Oracle database stores the rows of a nested table
SYSTOOLS
in no particular order. When you retrieve a nested table from the database into a PL/SQL
variable, the rows are given consecutive subscripts starting at 1. This gives you an array-like
access to individual rows.
Nested tables are initially dense, but they can become sparse through deletions and, therefore,
have nonconsecutive subscripts.
55 555
SYSTOOLS
56 566
57 577
88 888
SYSTOOLS
TABLE STORE AS clause in the CREATE TABLE statement. The storage table inherits
storage options from the outermost table.
To distinguish between nested table rows belonging to different parent table rows, a system-
generated nested table identifier that is unique for each outer row enclosing a nested table is
created.
Operations on storage tables are performed implicitly by the system. You should not access or
manipulate the storage table, except implicitly through its containing objects.
The column privileges of the parent table are transferred to the nested table.
SYSTOOLS
4 - 15 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
You can create a nested table data type in the database, which makes the data type available to
use in places such as columns in database tables, variables in PL/SQL programs, and attributes
of object types.
Before you can define a database table containing a nested table, you must first create the data
type for the collection in the database.
Use the syntax shown in the slide to create collection types in the database.
Creating Collections in PL/SQL
You can also create a nested table in PL/SQL. Use the syntax shown in the slide to create
collection types in PL/SQL.
Note: Collections can be nested. Collections of collections are also possible.
SYSTOOLS
supplier NUMBER(5),
requester NUMBER(4),
ordered DATE,
items typ_item_nst)
NESTED TABLE items STORE AS item_stor_tab
/
SYSTOOLS
declaration.
3. Create the pOrder table and use the nested table type in a column declaration, which
includes an arbitrary number of items based on the typ_item_nst type. Thus, each
row of pOrder may contain a table of items.
The NESTED TABLE STORE AS clause is required to indicate the name of the storage
table in which the rows of all values of the nested table reside. The storage table is created
in the same schema and the same tablespace as the parent table.
Note: The USER_COLL_TYPES dictionary view holds information about collections.
SYSTOOLS
55 555
500 50 5000 30-OCT-07
56 566
800 80 8000 31-OCT-07
57 577
PRODID PRICE
88 888 2
SYSTOOLS
pass two elements to the TYP_ITEM() constructor, and then pass the results to the
TYP_ITEM_NST() constructor to build the nested table structure.
The first INSERT statement builds the nested table with three subelement rows.
The second INSERT statement builds the nested table with one subelement row.
SYSTOOLS
FROM porder p2, TABLE(p2.items) p1;
SYSTOOLS
Another method to display the output is to unnest the collection such that each collection
element appears on a row by itself. You can use the TABLE expression in the FROM clause to
unnest a collection.
Querying Collections with the TABLE Expression
To view collections in a conventional format, you must unnest, or flatten, the collection
attribute of a row into one or more relational rows. You can do this by using a TABLE
expression with the collection. A TABLE expression enables you to query a collection in the
FROM clause like a table. In effect, you join the nested table with the row that contains the
nested table without writing a JOIN statement.
The collection column in the TABLE expression uses a table alias to identify the containing
table.
SYSTOOLS
4 - 19 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
In the preceding syntax, subscript is an expression that yields a positive integer. For nested
tables, the integer must lie in the range 1 to 2147483647. For varrays, the integer must lie in
the range 1 to maximum_size.
SYSTOOLS
p_new_items(i).price*.95);
END LOOP;
END IF;
UPDATE pOrder
SET items = v_with_discount
WHERE ordid = p_ordid;
END;
SYSTOOLS
• A local variable V_WITH_DISCOUNT is defined with the nested table data type
TYP_ITEM_NST.
• A collection method, called COUNT, is used to determine the number of items in the
nested table.
• If more than two items are counted in the collection, the local nested table variable
V_WITH_DISCOUNT is updated with the product ID and a 5% discount on the price.
• To reference an element in the collection, the subscript i, representing an integer from the
current loop iteration, is used with the constructor method to identify the row of the nested
table.
-- caller pgm:
DECLARE
v_form_items typ_item_nst:= typ_item_nst(); v_form_items variable
BEGIN
PRODID PRICE
-- let's say the form holds 4 items
v_form_items.EXTEND(4); 1804 65
v_form_items(1) := typ_item(1804, 65);
v_form_items(2) := typ_item(3172, 42); 3172 42
v_form_items(3) := typ_item(3337, 800);
v_form_items(4) := typ_item(2144, 14); 3337 800
add_order_items(800, v_form_items); 2144 14
END;
SYSTOOLS
500 50 5000 30-OCT-07 PRODID PRICE
3172 42
3337 800
2144 14
SYSTOOLS
• The nested table variable is populated with four rows of elements by constructing a row of
the nested table with the TYP_ITEM constructor.
• The nested table variable is passed as a parameter to the ADD_ORDER_ITEMS procedure
shown on the previous page.
• The ADD_ORDER_ITEMS procedure updates the ITEMS nested table column in the
pOrder table with the contents of the nested table parameter passed into the routine.
• Understanding collections
• Using associative arrays
• Using nested tables
• Using varrays
• Working with collections
• Programming for collection exceptions
• Summarizing collections
SYSTOOLS
4 - 22 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Varray:
SYSTOOLS
4 - 23 Copyright © 2008, Oracle. All rights reserved.
Understanding Varrays
Varrays are also collections of homogeneous elements that hold a fixed number of elements
(although you can change the number of elements at run time). They use sequential numbers
as subscripts.
You can define varrays as a SQL type, thereby allowing varrays to be stored in database tables.
SYSTOOLS
They can be stored and retrieved through SQL, but with less flexibility than nested tables. You
can reference individual elements for array operations, or manipulate the collection as a whole.
You can define varrays in PL/SQL to be used during PL/SQL program execution.
Varrays are always bounded and never sparse. You can specify the maximum size of the
varray in its type definition. Its index has a fixed lower bound of 1 and an extensible upper
bound. A varray can contain a varying number of elements, from zero (when empty) to the
maximum specified in its type definition.
To reference an element, you can use the standard subscripting syntax.
SYSTOOLS
dept_id NUMBER(2),
name VARCHAR2(25),
budget NUMBER(12,2),
projects typ_ProjectList) -- declare varray as column
/
Example
The example above shows how to create a table based on a varray.
1. Create the TYP_PROJECT type, which holds the information for a project.
2. Create the TYP_ PROJECTLIST type, which is created as a varray of the project type.
The varray contains a maximum of 50 elements.
3. Create the DEPARTMENT table and use the varray type in a column declaration. Each
SYSTOOLS
element of the varray will store a project object.
This example demonstrates how to create a varray of phone numbers, and then use it in a
CUSTOMERS table (The OE sample schema uses this definition.):
CREATE TYPE phone_list_typ
AS VARRAY(5) OF VARCHAR2(25);
/
CREATE TABLE customers
(customer_id NUMBER(6)
,cust_first_name VARCHAR2(50)
,cust_last_name VARCHAR2(50)
,cust_address cust_address_typ(100)
,phone_numbers phone_list_typ
...
);
DEPARTMENT table
SYSTOOLS
DEPT_ID NAME BUDGET PROJECTS
PROJECT_NO TITLE COSTS
Example (continued)
To add rows to the DEPARTMENT table that contains the PROJECTS varray column, you use
the INSERT statement. The structure of the varray column is identified with the constructor
methods.
• TYP_PROJECTLIST() constructor constructs the varray data type.
• TYP_PROJECT() constructs the elements for the rows of the varray data type.
SYSTOOLS
The first INSERT statement adds three rows to the PROJECTS varray for department 10.
The second INSERT statement adds one row to the PROJECTS varray for department 20.
SYSTOOLS
SELECT d2.dept_id, d2.name, d1.*
FROM department d2, TABLE(d2.projects) d1;
SYSTOOLS
In the second example, the output is unnested such that each collection element appears on a
row by itself. You can use the TABLE expression in the FROM clause to unnest a collection.
• Understanding collections
• Using associative arrays
• Using nested tables
• Using varrays
• Working with collections
• Programming for collection exceptions
• Summarizing collections
SYSTOOLS
4 - 27 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
(p_deptno NUMBER, p_new_project typ_Project,
p_position NUMBER);
FUNCTION manipulate_project (p_dept_id NUMBER)
RETURN typ_projectlist;
FUNCTION check_costs (p_project_list typ_projectlist)
RETURN boolean;
END manage_dept_proj;
SYSTOOLS
collections are instantiated when you enter the block or subprogram and cease to exist
when you exit. In a package, collections are instantiated when you first reference the
package and cease to exist when you end the database session.
SYSTOOLS
CREATE OR REPLACE PACKAGE BODY manage_dept_proj
AS
PROCEDURE allocate_new_proj_list
(p_dept_id NUMBER, p_name VARCHAR2, p_budget NUMBER)
IS
v_accounting_project typ_projectlist;
BEGIN -- this example uses a constructor
v_accounting_project :=
typ_ProjectList
(typ_Project (1, 'Dsgn New Expense Rpt', 3250),
typ_Project (2, 'Outsource Payroll', 12350),
typ_Project (3, 'Audit Accounts Payable',1425));
INSERT INTO department VALUES
(p_dept_id, p_name, p_budget, v_accounting_project);
END allocate_new_proj_list;
SYSTOOLS
FUNCTION get_dept_project (p_dept_id NUMBER)
RETURN typ_projectlist
IS
v_accounting_project typ_projectlist;
BEGIN
-- this example uses a fetch from the database
SELECT projects
INTO v_accounting_project
FROM department
WHERE dept_id = p_dept_id;
RETURN v_accounting_project;
END get_dept_project;
PROCEDURE update_a_project
(p_deptno NUMBER, p_new_project typ_Project,
p_position NUMBER)
SYSTOOLS
IS
v_my_projects typ_ProjectList;
BEGIN
v_my_projects := get_dept_project (p_deptno);
v_my_projects.EXTEND; --make room for new project
/* Move varray elements forward */
FOR i IN REVERSE p_position..v_my_projects.LAST - 1 LOOP
v_my_projects(i + 1) := v_my_projects(i);
END LOOP;
v_my_projects(p_position) := p_new_project; -- add new
-- project
UPDATE department SET projects = v_my_projects
WHERE dept_id = p_deptno;
END update_a_project;
-- continued on next page
SYSTOOLS
FUNCTION manipulate_project (p_dept_id NUMBER)
IS
RETURN typ_projectlist
v_accounting_project typ_projectlist;
v_changed_list typ_projectlist;
BEGIN
SELECT projects
INTO v_accounting_project
FROM department
WHERE dept_id = p_dept_id;
-- this example assigns one collection to another
v_changed_list := v_accounting_project;
RETURN v_changed_list;
END manipulate_project;
SYSTOOLS
FUNCTION check_costs (p_project_list typ_projectlist)
RETURN boolean
IS
c_max_allowed NUMBER := 10000000;
i INTEGER;
v_flag BOOLEAN := FALSE;
BEGIN
i := p_project_list.FIRST ;
WHILE i IS NOT NULL LOOP
IF p_project_list(i).cost > c_max_allowed then
v_flag := TRUE;
dbms_output.put_line (p_project_list(i).title ||
' exceeded allowable budget.');
RETURN TRUE;
END IF;
i := p_project_list.NEXT(i);
SYSTOOLS
END LOOP;
RETURN null;
END check_costs;
END manage_dept_proj;
SYSTOOLS
typ_ProjectList
(typ_Project (1, 'Dsgn New Expense Rpt', 3250),
typ_Project (2, 'Outsource Payroll', 12350),
typ_Project (3, 'Audit Accounts Payable',1425));
INSERT INTO department
VALUES(p_dept_id, p_name, p_budget, v_accounting_project);
END allocate_new_proj_list;
Initializing Collections
Until you initialize it, a collection is atomically null (that is, the collection itself is null, not its
elements). To initialize a collection, you can use one of the following methods:
• Use a constructor, which is a system-defined function with the same name as the
collection type. A constructor allows the creation of an object from an object type.
Invoking a constructor is a way to instantiate (create) an object. This function “constructs”
SYSTOOLS
collections from the elements passed to it. In the example shown in the slide, you pass
three elements to the typ_ProjectList() constructor, which returns a varray
containing those elements.
• Read an entire collection from the database using a fetch.
• Assign another collection variable directly. You can copy the entire contents of one
collection to another as long as both are built from the same data type.
SYSTOOLS
BEGIN
SELECT projects INTO v_accounting_project
FROM department WHERE dept_id = p_dept_id;
-- this example assigns one collection to another
v_changed_list := v_accounting_project;
RETURN v_changed_list;
END manipulate_project;
SYSTOOLS
END;
SYSTOOLS
Project #: 1001
Title: Travel Monitor
Cost: 400000
Project #: 1002
Title: Open World
Cost: 10000000
SYSTOOLS
Whereas the value of 10 is hard-coded, you can have a form interface to query the user for a
department value that can then be passed into the routine.
• EXISTS
• COUNT
• LIMIT
• FIRST and LAST
• PRIOR and NEXT
• EXTEND
• TRIM
• DELETE
SYSTOOLS
collection_name.method_name [(parameters)]
SYSTOOLS
SYSTOOLS
Function or Description
Procedure
EXISTS Returns TRUE if the nth element in a collection exists; otherwise,
EXISTS(N) returns FALSE.
COUNT Returns the number of elements that a collection contains.
LIMIT For nested tables that have no maximum size, LIMIT returns NULL;
for varrays, LIMIT returns the maximum number of elements that a
varray can contain.
FIRST and Returns the first and last (smallest and largest) index numbers in a
LAST collection, respectively.
PRIOR and PRIOR(n) returns the index number that precedes index n in a
NEXT collection; NEXT(n) returns the index number that follows index n.
EXTEND Appends one null element. EXTEND(n) appends n elements;
EXTEND(n, i) appends n copies of the ith element.
TRIM Removes one element from the end; TRIM(n) removes n elements
SYSTOOLS
from the end of a collection
DELETE Removes all elements from a nested or associative array table.
DELETE(n) removes the nth element ; DELETE(m, n) removes a
range. Note: Does not work on varrays.
SYSTOOLS
SYSTOOLS
RETURN TRUE;
END IF;
i := p_project_list.NEXT(i);
END LOOP;
RETURN null;
END check_costs;
Traversing Collections
In the example in the slide, the FIRST method finds the smallest index number, the NEXT
method traverses the collection starting at the first index.
You can use the PRIOR and NEXT methods to traverse collections indexed by any series of
subscripts. In the example shown, the NEXT method is used to traverse a varray.
SYSTOOLS
PRIOR(n) returns the index number that precedes index n in a collection. NEXT(n) returns
the index number that succeeds index n. If n has no predecessor, PRIOR(n) returns NULL.
Likewise, if n has no successor, NEXT(n) returns NULL. PRIOR is the inverse of NEXT.
PRIOR and NEXT do not wrap from one end of a collection to the other.
When traversing elements, PRIOR and NEXT ignore deleted elements.
SYSTOOLS
Audit Accounts Payable exceeded allowable budget.
Project rejected: overbudget
PROJECT_NO TITLE COSTS
V_PROJECT_LIST variable:
1 Dsgn New Expense Rpt 3250
2 Outsource Payroll 120000
3 Audit Accounts Payable 14250000
SYSTOOLS
A project with three elements is constructed and passed to the CHECK_COSTS function. The
CHECK_COSTS function returns true, because the third element of the varray exceeds the
value of the maximum allowed costs.
Although the sample caller program has the varray values hard-coded, you could have some
sort of form interface where the user enters the values for projects and the form calls the
CHECK_COSTS function.
PROCEDURE update_a_project
(p_deptno NUMBER, p_new_project typ_Project, p_position NUMBER)
IS
v_my_projects typ_ProjectList;
BEGIN
v_my_projects := get_dept_project (p_deptno);
v_my_projects.EXTEND; --make room for new project
/* Move varray elements forward */
FOR i IN REVERSE p_position..v_my_projects.LAST - 1 LOOP
v_my_projects(i + 1) := v_my_projects(i);
END LOOP;
v_my_projects(p_position) := p_new_project; -- insert new one
SYSTOOLS
UPDATE department SET projects = v_my_projects
WHERE dept_id = p_deptno;
END update_a_project;
SYSTOOLS
This code essentially shuffles the elements of a project so that you can insert a new element in
a particular position.
SYSTOOLS
FROM department d2, TABLE(d2.projects) d1;
SYSTOOLS
If you execute the following code, the AQM project element is shuffled to position 3 and the
CQN project element is inserted at position 2. :
BEGIN
manage_dept_proj.update_a_project(20,
typ_Project(2003, 'CQN', 85000), 2);
END;
• Understanding collections
• Using associative arrays
• Using nested tables
• Using varrays
• Working with collections
• Programming for collection exceptions
• Summarizing collections
SYSTOOLS
4 - 40 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
4 - 41 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
NO_DATA_FOUND A subscript designates an element that was
deleted.
SUBSCRIPT_BEYOND_COUNT A subscript exceeds the number of elements in a
collection.
SUBSCRIPT_OUTSIDE_LIMIT A subscript is outside the legal range.
VALUE_ERROR A subscript is null or not convertible to an integer.
DECLARE
TYPE NumList IS TABLE OF NUMBER;
nums NumList; -- atomically null
BEGIN
/* Assume execution continues despite the raised exceptions.
*/
nums(1) := 1; -- raises COLLECTION_IS_NULL
nums := NumList(1,2); -- initialize table
nums(NULL) := 3 -- raises VALUE_ERROR
nums(0) := 3; -- raises SUBSCRIPT_OUTSIDE_LIMIT
SYSTOOLS
nums(3) := 3; -- raises SUBSCRIPT_BEYOND_COUNT
nums.DELETE(1); -- delete element 1
IF nums(1) = 1 THEN -- raises NO_DATA_FOUND
...
SYSTOOLS
• Understanding collections
• Using associative arrays
• Using nested tables
• Using varrays
• Working with collections
• Programming for collection exceptions
• Summarizing collections
SYSTOOLS
4 - 43 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
retain ordering retain ordering ordering and ordering and ordering and
and subscripts and subscripts subscripts subscripts subscripts
SYSTOOLS
• Use nested tables when:
- You need persistence.
- You need to pass the collection as a parameter.
Choosing Between Nested Tables and Varrays
• Use varrays when:
- The number of elements is known in advance.
- The elements are usually all accessed in sequence.
• Use nested tables when:
- The index values are not consecutive.
- There is no predefined upper bound for the index values.
- You need to delete or update some, not all, elements simultaneously.
- You would usually create a separate lookup table with multiple entries for each row
of the main table and access it through join queries.
Oracle Database 11g: Advanced PL/SQL 4 - 44
SYSTOOLS
Guidelines for Using Collections Effectively
SYSTOOLS
4 - 45 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
elements, a nested table is simpler to use.
• If your data set is not very large and it is important to preserve the order of elements in a
collection column, use varrays. For example, if you know that the collection will not
contain more than 10 elements in each row, you can use a varray with a limit of 10.
• If you do not want to deal with deletions in the middle of the data set, use varrays.
• If you expect to retrieve the entire collection simultaneously, use varrays.
• Varrays do not allow piecewise updates.
• After deleting the elements, you can release the unused memory with the
DBMS_SESSION.FREE_UNUSED_USER_MEMORY procedure.
Note: If your application requires negative subscripts, you can use only associative arrays.
Summary
Collections are a grouping of elements, all of the same type. The types of collections are
nested tables, varrays, and associative arrays. You can define nested tables and varrays in the
database. Nested tables, varrays, and associative arrays can be used in a PL/SQL program.
When using collections in PL/SQL programs, you can access the collection elements, use
SYSTOOLS
predefined collection methods, and use the exceptions that are commonly encountered with
collections.
There are guidelines for using collections effectively and for determining which collection
type is appropriate under specific circumstances.
SYSTOOLS
4 - 47 Copyright © 2008, Oracle. All rights reserved.
Practice 4: Overview
In this practice, you analyze collections for common errors, create a collection, and then write
a PL/SQL package to manipulate the collection.
Use the OE schema for this practice.
For detailed instructions on performing this practice, see Appendix A, “Practice Solutions.”
SYSTOOLS
SYSTOOLS
the collection.
Analyzing Collections
1. Examine the following definitions. Run the lab_04_01.sql script to create these
objects.
CREATE TYPE typ_item AS OBJECT --create object
(prodid NUMBER(5),
price NUMBER(7,2) )
/
CREATE TYPE typ_item_nst -- define nested table type
AS TABLE OF typ_item
/
CREATE TABLE pOrder ( -- create database table
ordid NUMBER(5),
supplier NUMBER(5),
SYSTOOLS
requester NUMBER(4),
ordered DATE,
items typ_item_nst)
NESTED TABLE items STORE AS item_stor_tab
/
2. The following code generates an error. Run the lab_04_02.sql script to generate
and view the error.
BEGIN
-- Insert an order
INSERT INTO pOrder
(ordid, supplier, requester, ordered, items)
VALUES (1000, 12345, 9876, SYSDATE, NULL);
-- insert the items for the order created
INSERT INTO TABLE (SELECT items
FROM pOrder
SYSTOOLS
WHERE ordid = 1000)
VALUES(typ_item(99, 129.00));
END;
/
SYSTOOLS
3. Examine the following code, which produces an error. Which line causes the error,
and how do you fix it?
(Note: You can run the lab_04_03.sql script to view the error output).
DECLARE
TYPE credit_card_typ
IS VARRAY(100) OF VARCHAR2(30);
BEGIN
v_mc.EXTEND;
SYSTOOLS
v_visa.EXTEND;
v_am.EXTEND;
v_disc.EXTEND;
v_dc.EXTEND;
END;
/
SYSTOOLS
SYSTOOLS
In the following practice exercises, you implement a nested table column in the CUSTOMERS
table and write PL/SQL code to manipulate the nested table.
4. Create a nested table to hold credit card information.
a. Create an object type called typ_cr_card. It should have the following
specification:
card_type VARCHAR2(25)
card_num NUMBER
b. Create a nested table type called typ_cr_card_nst that is a table of
typ_cr_card.
c. Add a column to the CUSTOMERS table called credit_cards. Make this column
a nested table of type typ_cr_card_nst. You can use the following syntax:
ALTER TABLE customers ADD
(credit_cards typ_cr_card_nst)
NESTED TABLE credit_cards STORE AD c_c_store_tab;
SYSTOOLS
5. Create a PL/SQL package that manipulates the credit_cards column in the
CUSTOMERS table.
a. Open the lab_04_05.sql file. It contains the package specification and part of
the package body.
b. Complete the code so that the package:
- Inserts credit card information (the credit card name and number for a specific
customer)
- Displays credit card information in an unnested format
SYSTOOLS
PROCEDURE display_card_info
(p_cust_id NUMBER);
END credit_card_pkg; -- package spec
/
Practice 4 (continued)
Using Collections (continued)
SYSTOOLS
CREATE OR REPLACE PACKAGE BODY credit_card_pkg
IS
PROCEDURE update_card_info
(p_cust_id NUMBER, p_card_type VARCHAR2, p_card_no
VARCHAR2)
IS
v_card_info typ_cr_card_nst;
i INTEGER;
BEGIN
SELECT credit_cards
INTO v_card_info
FROM customers
WHERE customer_id = p_cust_id;
IF v_card_info.EXISTS(1) THEN
SYSTOOLS
-- cards exist, add more
END IF;
END update_card_info;
PROCEDURE display_card_info
(p_cust_id NUMBER)
IS
v_card_info typ_cr_card_nst;
SYSTOOLS
i INTEGER;
BEGIN
SELECT credit_cards
INTO v_card_info
FROM customers
WHERE customer_id = p_cust_id;
END display_card_info;
END credit_card_pkg; -- package body
/
SYSTOOLS
6. Test your package with the following statements and compare the output:
EXECUTE credit_card_pkg.display_card_info(120)
Customer has no credit cards.
PL/SQL procedure successfully completed.
EXECUTE credit_card_pkg.update_card_info –
(120, 'Visa', 11111111)
PL/SQL procedure successfully completed.
SELECT credit_cards
FROM customers
WHERE customer_id = 120;
CREDIT_CARDS(CARD_TYPE, CARD_NUM)
-------------------------------------------------
SYSTOOLS
TYP_CR_CARD_NST(TYP_CR_CARD('Visa', 11111111))
EXECUTE credit_card_pkg.display_card_info(120)
Card Type: Visa / Card No: 11111111
PL/SQL procedure successfully completed.
EXECUTE credit_card_pkg.update_card_info –
(120, 'MC', 2323232323)
PL/SQL procedure successfully completed.
EXECUTE credit_card_pkg.update_card_info –
(120, 'DC', 4444444)
PL/SQL procedure successfully completed.
EXECUTE credit_card_pkg.display_card_info(120)
Card Type: Visa / Card No: 11111111
SYSTOOLS
Card Type: MC / Card No: 2323232323
Card Type: DC / Card No: 4444444
PL/SQL procedure successfully completed.
SYSTOOLS
7. Write a SELECT statement against the credit_cards column to unnest the data. Use
the TABLE expression. Use SQL*Plus.
SELECT credit_cards
FROM customers
WHERE customer_id = 120;
CREDIT_CARDS(CARD_TYPE, CARD_NUM)
--------------------------------------------------------
TYP_CR_CARD_NST(TYP_CR_CARD('Visa', 11111111),
TYP_CR_CARD('MC', 2323232323), TYP_CR_CARD('DC',
4444444))
SYSTOOLS
rewrite it using the TABLE expression so that the results look like this:
SYSTOOLS
SYSTOOLS
SYSTOOLS
SYSTOOLS
Using Advanced Interface Methods
SYSTOOLS
Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Objectives
SYSTOOLS
After completing this lesson, you should be able to do the
following:
• Execute external C programs from PL/SQL
• Execute Java programs from PL/SQL
SYSTOOLS
5-2 Copyright © 2008, Oracle. All rights reserved.
Objectives
In this lesson, you learn how to implement an external C routine from PL/SQL code and how to
incorporate Java code into your PL/SQL programs.
SYSTOOLS
SYSTOOLS
With external procedures, you can make “callouts”
and, optionally, “callbacks” through PL/SQL.
Java class
DECLARE
method
BEGIN
EXCEPTION
C routine
SYSTOOLS
END;
PL/SQL External
subprogram procedure
SYSTOOLS
PL/SQL or SQL. With C, you publish the routine through a library schema object, which is
called from PL/SQL, that contains the compiled library file name that is stored on the operating
system. With Java, publishing the routine is accomplished through creating a class libunit.
A callout is a call to the external procedure from your PL/SQL code.
A callback occurs when the external procedure calls back to the database to perform SQL
operations. If the external procedure is to execute SQL or PL/SQL, it must “call back” to the
database server process to get this work done.
An external procedure enables you to:
• Move computation-bound programs from the client to the server where they execute faster
(because they avoid the round trips entailed in across-network communication)
• Interface the database server with external systems and data sources
• Extend the functionality of the database itself
SYSTOOLS
• External procedures integrate the strength and capability of
different languages to give transparent access to these
routines within the database.
• Extensibility: External procedures provide functionality in the
database that is specific to a particular application, company,
or technological area.
• Reusability: External procedures can be shared by all users
on a database, and they can be moved to other databases
or computers, thereby providing standard functionality with
SYSTOOLS
limited cost in development, maintenance, and deployment.
SYSTOOLS
different index or sorting mechanisms as an external procedure to implement data cartridges.
Example
A company has very complicated statistics programs written in C. The customer wants to access
the data stored in an Oracle database and pass the data into the C programs. After execution of
the C programs, depending on the result of the evaluations, data is inserted into the appropriate
Oracle database tables.
SYSTOOLS Listener
DECLARE process
BEGIN
EXCEPTION
extproc
END; process
PL/SQL Alias
subprogram library
SYSTOOLS User
process
External
procedure Shared library
or directory
SYSTOOLS
specification and mapping to the PL/SQL library
• extproc process: A session-specific process that executes external procedures
• Listener process: A process that starts the extproc process and assigns it to the process
executing the PL/SQL subprogram
SYSTOOLS 2
3 Listener
DECLARE process
BEGIN
4
EXCEPTION
6 extproc
END; process
7
PL/SQL Alias 5
subprogram library
SYSTOOLS
BEGIN
myproc
User External
process procedure Shared library
1
SYSTOOLS
throughout your Oracle session until you log off.
5. The extproc process loads the shared library.
6. The extproc process links the server to the external file and executes the external
procedure.
7. The data and status are returned to the server.
SYSTOOLS
• The extproc process services the execution of external
procedures for the duration of the session until the user
logs off.
• Each session uses a different extproc process to execute
external procedures.
• The listener must be configured to allow the server to be
associated with the extproc process.
• The listener must be on the same machine as the server.
SYSTOOLS
5-7 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
- Raises exceptions if necessary
- Converts C back to PL/SQL
- Sends arguments or exceptions back to the server process
SYSTOOLS Listener
DECLARE process
BEGIN
listener.ora
EXCEPTION
extproc
END; process
PL/SQL Alias
subprogram library
SYSTOOLStnsnames.ora
External
procedure Shared library
SYSTOOLS
resides in a dynamic library. The Oracle Database Server runs the extproc process to load the
dynamic library and to execute the external procedure.
3GL Call Dependencies: Example
Libraries are objects with the following dependencies:
Given library L1 and procedure P1, which depends on L1, when the procedure P1 is executed,
library L1 is loaded, and the corresponding external library is dynamically loaded. P1 can now
use the external library handle and call the appropriate external functions.
If L1 is dropped, P1 is invalidated and needs to be recompiled.
SYSTOOLS
6. Execute the PL/SQL subprogram that invokes the external
procedure.
SYSTOOLS
you map the C arguments to the PL/SQL parameters, and execute the PL/SQL subprogram that
invokes the external routine.
SYSTOOLS
5 - 10 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
file. The DBA must give you EXECUTE privileges on the library object so that you can publish
the external procedure, and then call it from a PL/SQL program.
Steps
1, 2. Steps 1 and 2 vary for each operating system. Consult your operating system or the
compiler documentation.
3. Create an alias library object by using the CREATE LIBRARY command:
CONNECT /as sysdba
The example shows the creation of a database object called c_utility, which references the
location of the file and the name of the operating system file, calc_tax.dll.
SYSTOOLS
GRANT EXECUTE ON c_utility TO OE;
5. Publish the external C routine.
6. Call the external C routine from PL/SQL.
Dictionary Information
The alias library definitions are stored in the USER_LIBRARIES and ALL_LIBRARIES data
dictionary views.
SYSTOOLS
SYSTOOLS
External routine
SYSTOOLS
within the
Library procedure
SYSTOOLS
• Access is controlled through the alias library.
You can publish the external procedure in PL/SQL by:
• Identifying the characteristics of the C procedure to the PL/SQL program
• Accessing the library through PL/SQL
The package specification does not require changes. You do not need definitions for the external
procedure.
SYSTOOLS
Call specifications enable:
• Dispatching the appropriate C or Java target procedure
• Data type conversions
• Parameter mode mappings
• Automatic memory allocation and cleanup
• Purity constraints to be specified, where necessary, for
packaged functions that are called from SQL
• Calling Java methods or C procedures from database
triggers
SYSTOOLS
• Location flexibility
SYSTOOLS
To use an existing program as an external procedure, load, publish, and then call it.
Call specifications can be specified in any of the following locations:
• Stand-alone PL/SQL procedures and functions
• PL/SQL package specifications
• PL/SQL package bodies
• Object type specifications
• Object type bodies
Note: For functions that have the RESTRICT_REFERENCES pragma, use the TRUST option.
The SQL engine cannot analyze those functions to determine whether they are free from side
effects. The TRUST option makes it easier to call the Java and C procedures.
SYSTOOLS
• Identify the external body within a PL/SQL program to
publish the external C procedure.
CREATE OR REPLACE FUNCTION function_name
(parameter_list)
RETURN datatype
regularbody | externalbody
END;
SYSTOOLS
LIBRARY libname
[NAME C_function_name]
[CALLING STANDARD C | PASCAL]
[WITH CONTEXT]
[PARAMETERS (param_1, [param_n]);
SYSTOOLS
routine was written (defaults to C)
LIBRARY libname Is the name of the library database object
NAME Represents the name of the C function; if
"C_function_name" omitted, the external procedure name must
match the name of the PL/SQL
subprogram
CALLING STANDARD Specifies the Windows NT calling
standard (C or Pascal) under which the
external routine was compiled (defaults
to C)
WITH CONTEXT Specifies that a context pointer is passed
to the external routine for callbacks
parameters Identifies arguments passed to the external
routine
SYSTOOLS
• The parameter list:
parameter_list_element
[ , parameter_list_element ]
SYSTOOLS
5 - 15 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
name [INDICATOR] is being passed to the external routine; the
INDICATOR keyword is used to map a C
parameter whose value indicates whether
the PL/SQL parameter is null
RETURN INDICATOR Corresponds to the C parameter that
returns a null indicator for the function
CONTEXT Specifies that a context pointer will be
passed to the external routine
BY REFERENCE In C, you can pass IN scalar parameters
by value (the value is passed) or by
reference (a pointer to the value is
passed). Use BY REFERENCE to pass the
parameter by reference.
External_datatype Is the external data type that maps to a C
data type
Note: The PARAMETER clause is optional if the mapping of the parameters is done on a
positional basis, and indicators, reference, and context are not needed.
Oracle Database 11g: Advanced PL/SQL 5 - 15
Publishing an External C Routine
Example
SYSTOOLS
• Publish a C function called calc_tax from a PL/SQL function.
CREATE FUNCTION tax_amt (
x BINARY_INTEGER)
RETURN BINARY_INTEGER
AS LANGUAGE C
LIBRARY sys.c_utility
NAME "calc_tax";
/
SYSTOOLS
• The C prototype:
int calc_tax (n);
Example
You have an external C function called calc_tax that takes in one argument, the total sales
amount. The function returns the tax amount calculated at 8%. The prototype for your
calc_tax function is as follows:
int calc_tax (n);
SYSTOOLS
To publish the calc_tax function in a stored PL/SQL function, use the AS LANGUAGE C
clause within the function definition. The NAME identifies the name of the C function. Double
quotation marks are used to preserve the case of the function defined in the C program. The
LIBRARY identifies the library object that locates the C file. The PARAMETERS clause is not
needed in this example, because the mapping of the parameters is done on a positional basis.
SYSTOOLS
1. Create and compile the external procedure in 3GL.
2. Link the external procedure with the shared library at the
operating system level.
3. Create an alias library schema object to map to the
operating system’s shared library.
4. Grant execute privileges on the library.
5. Publish the external C procedure by creating the PL/SQL
subprogram unit specification, which references the alias
library.
SYSTOOLS
6. Execute the PL/SQL subprogram that invokes the external
procedure.
SYSTOOLS
You can call the function in a cursor FOR loop or in any location where a PL/SQL function call
is allowed:
DECLARE
CURSOR cur_orders IS
SELECT order_id, order_total
FROM orders;
v_tax NUMBER(8,2);
BEGIN
FOR order_record IN cur_orders
LOOP
v_tax := tax_amt(order_record.order_total);
DBMS_OUTPUT.PUT_LINE('Total tax: ' || v_tax);
END LOOP;
END;
SYSTOOLS
The Oracle database can store Java classes and Java source,
which:
• Are stored in the database as procedures, functions, or
triggers
• Run inside the database
• Manipulate data
SYSTOOLS
5 - 18 Copyright © 2008, Oracle. All rights reserved.
Java: Overview
The Oracle database can store Java classes (.class files) and Java source code (.java files),
which are stored in the database as procedures, functions, or triggers. These classes can
manipulate data but cannot display graphical user interface (GUI) elements such as Abstract
Window Toolkit (AWT) or Swing components. Running Java inside the database helps these
SYSTOOLS
Java classes to be called many times and manipulate large amounts of data without the
processing and network overhead that comes with running on the client machine.
You must write these named blocks, and then define them by using the loadjava command or
the SQL CREATE FUNCTION, CREATE PROCEDURE, CREATE TRIGGER, or CREATE
PACKAGE statements.
SYSTOOLS
1
CREATE
JAVA 2 Java
Virtual
4 Machine
libunits
/home/java/bin/Agent.class
SYSTOOLS
When the CREATE JAVA statement is invoked, the Java Virtual Machine library manager on
the server loads the Java binaries and resources from the local BFILEs or LOB columns into the
RDBMS libunits. Libunits can be considered analogous to the DLLs written in C, although they
map one-to-one with Java classes, whereas DLLs can contain multiple routines.
SYSTOOLS
Publish Execute
SYSTOOLS
2. Publish the Java class method by creating the PL/SQL subprogram unit specification that
references the Java class methods.
3. Execute the PL/SQL subprogram that invokes the Java class method.
SYSTOOLS
1. Upload the Java file.
– At the operating system, use the loadjava command-line
utility to load either the Java class file or the Java source file.
• To load the Java source file, use:
>loadjava –user oe/oe Factorial.java
• To load the Java class file, use:
>loadjava –user oe/oe Factorial.class
– If you load the Java source file, you do not need to load the
SYSTOOLS
Java class file.
SYSTOOLS
database, where they are stored as Java schema objects. You can run loadjava from the
command line or from an application.
After the file is loaded, it is visible in the data dictionary views.
SELECT object_name, object_type FROM user_objects
WHERE object_type like 'J%';
OBJECT_NAME OBJECT_TYPE
------------------------------ ------------------------
Factorial JAVA CLASS
Factorial JAVA SOURCE
SYSTOOLS
2. Publish the Java class method by creating the PL/SQL
subprogram unit specification that references the Java
class methods.
– Identify the external body within a PL/SQL program to publish
the Java class method.
– The external body contains the name of the Java class
method.
CREATE OR REPLACE
{ PROCEDURE procedure_name [(parameter_list)]
| FUNCTION function_name [(parameter_list]...)]
RETURN datatype}
regularbody | externalbody
SYSTOOLS
END;
SYSTOOLS
• Example:
SYSTOOLS
CREATE OR REPLACE FUNCTION plstojavafac_fun
(N NUMBER)
RETURN NUMBER
AS
LANGUAGE JAVA
NAME 'Factorial.calcFactorial
(int) return int';
• Java method definition:
public class Factorial {
SYSTOOLS
public static int calcFactorial (int n) {
if (n == 1) return 1;
else return n * calcFactorial (n - 1) ;
}
}
Example
You want to publish a Java method named calcFactorial that returns the factorial of its
argument, as shown above:
• The PL/SQL function plstojavafac_fun is created to identify the parameters and the
Java characteristics.
SYSTOOLS
• The NAME clause string uniquely identifies the Java method
• The parameter named N corresponds to the int argument
SYSTOOLS
1. Upload the Java file.
2. Publish the Java class method by creating the PL/SQL
subprogram unit specification that references the Java
class methods.
3. Execute the PL/SQL subprogram that invokes the Java
class method.
SYSTOOLS
5 - 24 Copyright © 2008, Oracle. All rights reserved.
Example (continued)
You can call the calcFactorial class method by using the following command:
SYSTOOLS
120
Alternatively, to execute a SELECT statement from the DUAL table:
PLSTOJAVAFAC_FUN(5)
-------------------
120
SYSTOOLS
CREATE OR REPLACE PACKAGE Demo_pack
AUTHID DEFINER
AS
PROCEDURE plsToJ_InSpec_proc
(x BINARY_INTEGER, y VARCHAR2, z DATE)
END;
SYSTOOLS
(x BINARY_INTEGER, y VARCHAR2, z DATE)
IS LANGUAGE JAVA
NAME 'pkg1.class4.J_InSpec_meth
(int, java.lang.String, java.sql.Date)';
SYSTOOLS
external procedure. The details of the implementation appear only in the package body in the
declaration of the procedure body.
SYSTOOLS
In this lesson, you should have learned how to:
• Use external C routines and call them from your PL/SQL
programs
• Use Java methods and call them from your PL/SQL
programs
SYSTOOLS
5 - 26 Copyright © 2008, Oracle. All rights reserved.
Summary
You can embed calls to external C programs from your PL/SQL programs by publishing the
external routines in a PL/SQL block. You can take external Java programs and store them in the
database to be called from PL/SQL functions, procedures, and triggers.
SYSTOOLS
SYSTOOLS
This practice covers the following topics:
• Writing programs to interact with C routines
• Writing programs to interact with Java code
SYSTOOLS
5 - 27 Copyright © 2008, Oracle. All rights reserved.
Practice 5: Overview
In this practice, you write two PL/SQL programs: One program calls an external C routine and
the second program calls a Java routine.
Use the OE schema for this practice.
For detailed instructions about performing this practice, see Appendix A, “Practice Solutions.”
SYSTOOLS
SYSTOOLS
An external C routine definition is created for you. The .c file is stored in the D:\labs\labs
directory. This function returns the tax amount based on the total sales figure that is passed to
the function as a parameter. The.c file is named calc_tax.c. The function is defined as:
__declspec(dllexport)
int calc_tax(n)
int n;
{
int tax;
tax = (n*8)/100;
return (tax);
}
1. A DLL file called calc_tax.dll was created for you. Copy the file from the
D:\labs\labs directory into your
D:\app\Administrator\product\11.1.0\db_1\BIN directory.
SYSTOOLS
2. As the SYS user, create the alias library object. Name the library object c_code and define
its path as:
connect / as sysdba
3. Grant execute privilege on the library to the OE user by executing the following command:
GRANT EXECUTE ON c_code TO OE;
SYSTOOLS
NAME clauses of the function.
5. Create a procedure to call the call_c function that was created in the previous step.
Name this procedure C_OUTPUT. It has one numeric parameter. Include a
DBMS_OUTPUT.PUT_LINE statement so that you can view the results returned from your
C function.
SYSTOOLS
A Java method definition is created for you. The method accepts a 16-digit credit card number
as the argument and returns the formatted credit card number (4 digits followed by a space). The
name of the .class file is FormatCreditCardNo.class. The method is defined as:
SYSTOOLS
}
cardno[0]=newcc [0];
}
}
8. Publish the Java class method by defining a PL/SQL procedure named CCFORMAT. This
procedure accepts one IN OUT parameter.
9. Execute the Java class method. Define one SQL*Plus or SQL Developer variable, initialize
it, and use the EXECUTE command to execute the CCFORMAT procedure.
Your output should match the PRINT output as shown below.
SYSTOOLS
EXECUTE ccformat(:x);
PRINT x
X
-------------------
1234 5678 1234 5678
SYSTOOLS
SYSTOOLS
SYSTOOLS
Implementing Fine-Grained Access Control
for VPD
SYSTOOLS
Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Objectives
SYSTOOLS
After completing this lesson, you should be able to
do the following:
• Describe the process of fine-grained access control
• Implement and test fine-grained access control
SYSTOOLS
6-2 Copyright © 2008, Oracle. All rights reserved.
Objectives
In this lesson, you learn about the security features in the Oracle Database from an application
developer’s standpoint.
For more information about these features, refer to Oracle Supplied PL/SQL Packages and
Types Reference, Oracle Label Security Administrator’s Guide, Oracle Single Sign-On
SYSTOOLS
Application Developer’s Guide, and Oracle Security Overview.
SYSTOOLS
• Describing the process of fine-grained access control
• Implementing and testing fine-grained access control
SYSTOOLS
6-3 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
Fine-grained access control:
• Enables you to enforce security through a low level of
granularity
• Restricts users to viewing only “their” information
• Is implemented through a security policy attached to tables
• Is implemented by highly privileged system DBAs, perhaps
in coordination with developers
• Dynamically modifies user statements to fit the policy
SYSTOOLS
6-4 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
When you use fine-grained access control, you create security policy functions attached to the
table or view on which you based your application. When a user enters a data manipulation
language (DML) statement on that object, the Oracle server dynamically modifies the user’s
statement—transparently to the user—so that the statement implements the correct access
control.
Fine-grained access is also known as a virtual private database (VPD), because it implements
row-level security, essentially giving users access to their own private database. Fine-grained
means at the individual row level.
SYSTOOLS Table
SELECT
INSERT
UPDATE
Security
SELECT policies
DELETE
SYSTOOLS SELECT
Features
You can use fine-grained access control to implement security rules called policies with
functions, and then associate those security policies with tables or views. The database server
automatically enforces those security policies, no matter how the data is accessed.
A security policy is a collection of rules needed to enforce the appropriate privacy and security
SYSTOOLS
rules in the database itself, making it transparent to users of the data structure.
Attaching security policies to tables or views, rather than to applications, provides greater
security, simplicity, and flexibility.
You can:
• Use different policies for SELECT, INSERT, UPDATE, and DELETE statements
• Use security policies only where you need them
• Use multiple policies for each table, including building on top of base policies in packaged
applications
• Distinguish policies between different applications by using policy groups
SYSTOOLS
Implement the policy on the CUSTOMERS table:
“Account managers can see only their own
customers.”
Id
149
Security 3
2 SELECT 145
policies
145
4 149
Function:
SYSTOOLS
... 147
1 WHERE account_mgr_id = 148
147
...
149
5
148
Account manager 148
SYSTOOLS
2. Have the user (the account manager) enter a SQL statement.
3. Implement the security policy through the function that you created. The Oracle server calls
the function automatically.
4. Dynamically modify the user’s statement through the function.
5. Execute the dynamically modified statement.
SYSTOOLS
• You write a function to return the account manager ID:
account_mgr_id := (SELECT account_mgr_id
FROM customers
WHERE account_mgr_id =
SYS_CONTEXT ('userenv','session_user'));
SYSTOOLS
WHERE account_mgr_id = (SELECT account_mgr_id
FROM customers
WHERE account_mgr_id =
SYS_CONTEXT ('userenv','session_user'));
SYSTOOLS
successfully restricting access to other customers’ information, displaying only the information
relevant to the account manager.
Note: The SYS_CONTEXT function returns a value for an attribute, in this case, connection
attributes. This is explained in detail in the following pages.
SYSTOOLS
To implement the business rule “Account managers can see
only their own customers,” you have three options:
Option Comment
Modify all existing application code Does not ensure privacy enforcement
to include a predicate (a WHERE outside the application. Also, all
clause) for all SQL statements. application code may need to be
modified in the future as business rules
change.
Create views with the necessary This can be difficult to administer,
Predicates, and then create especially if there are a large number
synonyms with the same name as of views to track and manage.
the table names for these views.
SYSTOOLS
Create a VPD for each of the
account managers by creating policy
functions to generate dynamic
predicates. These predicates can
then be applied across all objects.
This option offers the best security
without major administrative overheads
and it also ensures complete
privacy of information.
SYSTOOLS
SYSTOOLS
• Describing the process of fine-grained
access control
• Implementing and testing fine-grained access control
SYSTOOLS
6-9 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• An application context is used to facilitate the
implementation of fine-grained access control.
• It is a named set of attribute/value pairs associated with a
PL/SQL package.
• Applications can have their own application-specific
contexts.
• Users cannot change their application’s context.
Context
SYSTOOLS
Implements
Attribute Value
Attached Associated
Security
to a with a
Session package policies
session
SYSTOOLS
with applications
A context is a named set of attribute/value pairs that are global to your session. You can define
an application context, name it, and associate a value with that context with a PL/SQL package.
An application context enables you to write applications that draw upon certain aspects of a
user’s session information. It provides a way to define, set, and access attributes that an
application can use to enforce access control—specifically, fine-grained access control.
Most applications contain information about the basis on which access is to be limited. In an
order entry application, for example, you limit the customers’ access their own orders
(ORDER_ID) and customer number (CUSTOMER_ID). Or, you may limit account managers
(ACCOUNT_MGR_ID) to view only their own customers. These values can be used as security
attributes. Your application can use a context to set values that are accessed within your code
and used to generate WHERE clause predicates for fine-grained access control.
An application context is owned by SYS.
SYSTOOLS
System
predefined
USERENV Context
Attribute Value
IP_ADDRESS 139.185.35.118
SESSION_USER oe
CURRENT_SCHEMA oe The function
DB_NAME orcl SYS_CONTEXT
returns a value
Application YOUR_DEFINED Context of an attribute
defined Attribute Value of a context.
customer_info cus_1000
account_mgr AM145
FROM DUAL;
SYSTOOLS
SELECT SYS_CONTEXT ('USERENV', 'SESSION_USER')
SYSTOOLS
With the SYS_CONTEXT function, you pass the context name and the attribute name. The
attribute value is returned.
The following statement returns the name of the database that is being accessed:
SELECT SYS_CONTEXT ('USERENV', 'DB_NAME')
FROM DUAL;
SYS_CONTEXT('USERENV','DB_NAME')
----------------------------------------------
ORCL
SYSTOOLS
CREATE [OR REPLACE] CONTEXT namespace
USING [schema.]plsql_package
SYSTOOLS
at the time of context creation.)
Context created.
SYSTOOLS
Because a context is associated with a PL/SQL package, you need to name the package that you
are associating with the context. This package does not need to exist at the time of context
creation.
SYSTOOLS
• Use the supplied package procedure
DBMS_SESSION.SET_CONTEXT to set a value for an
attribute within a context.
DBMS_SESSION.SET_CONTEXT('context_name',
'attribute_name',
'attribute_value')
SYSTOOLS
DBMS_SESSION.SET_CONTEXT('ORDER_CTX',
'ACCOUNT_MGR',
v_user)
...
Setting a Context
When a context is defined, you can use the DBMS_SESSION.SET_CONTEXT procedure to set
a value for an attribute within a context. The attribute is set in the package that is associated with
the context.
CREATE OR REPLACE PACKAGE orders_app_pkg
IS
SYSTOOLS
PROCEDURE set_app_context;
END;
/
CREATE OR REPLACE PACKAGE BODY orders_app_pkg
IS
c_context CONSTANT VARCHAR2(30) := 'ORDER_CTX';
PROCEDURE set_app_context
IS
v_user VARCHAR2(30);
BEGIN
SELECT user INTO v_user FROM dual;
DBMS_SESSION.SET_CONTEXT
(c_context, 'ACCOUNT_MGR', v_user);
END;
END;
/
Oracle Database 11g: Advanced PL/SQL 6 - 13
Setting a Context (continued)
In the example on the previous page, the ORDER_CTX context has the ACCOUNT_MGR attribute
SYSTOOLS
set to the current user logged (determined by the USER function).
For this example, assume that users AM145, AM147, AM148, and AM149 exist. As each user
logs on and the DBMS_SESSION.SET_CONTEXT is invoked, the attribute value for that
ACCOUNT_MGR is set to the user ID.
CONNECT AM145/oracle
Connected.
EXECUTE oe.orders_app_pkg.set_app_context
SYSTOOLS
SYS_CONTEXT('ORDER_CTX', 'ACCOUNT_MGR')
---------------------------------------------------------
AM145
If you switch the user ID, the attribute value is also changed to reflect the current user.
CONNECT AM147/oracle
Connected.
EXECUTE oe.orders_app_pkg.set_app_context
SYS_CONTEXT('ORDER_CTX', 'ACCOUNT_MGR')
---------------------------------------------------------
SYSTOOLS
AM147
SYSTOOLS
Follow these steps:
1. Set up a driving context.
CREATE OR REPLACE CONTEXT order_ctx
USING orders_app_pkg;
SYSTOOLS
4. Set up a logon trigger to call the package at logon time and
set the context.
5. Test the policy.
Implementing a Policy
In this example, assume that the users AM145, AM147, AM148, and AM149 exist. Next, create a
context and a package associated with the context. The package will be owned by OE.
Step 1: Set Up a Driving Context
Use the CREATE CONTEXT syntax to create a context.
SYSTOOLS
CONNECT /AS sysdba
SYSTOOLS
CREATE OR REPLACE PACKAGE orders_app_pkg
IS
PROCEDURE show_app_context;
PROCEDURE set_app_context;
FUNCTION the_predicate
(p_schema VARCHAR2, p_name VARCHAR2)
RETURN VARCHAR2;
END orders_app_pkg; -- package spec
/
SYSTOOLS
6 - 16 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
• set_app_context: This procedure sets a context attribute to a specific value.
• the_predicate: This function builds the predicate (the WHERE clause) that controls the
rows visible in the CUSTOMERS table to a user. (Note that this function requires two input
parameters. An error occurs when the policy is implemented if you exclude these two
parameters.)
SYSTOOLS
CREATE OR REPLACE PACKAGE BODY orders_app_pkg
IS
c_context CONSTANT VARCHAR2(30) := 'ORDER_CTX';
c_attrib CONSTANT VARCHAR2(30) := 'ACCOUNT_MGR';
PROCEDURE show_app_context
IS
BEGIN
DBMS_OUTPUT.PUT_LINE('Type: ' || c_attrib ||
' - ' || SYS_CONTEXT(c_context, c_attrib));
END show_app_context;
PROCEDURE set_app_context
IS
v_user VARCHAR2(30);
BEGIN
SYSTOOLS
SELECT user INTO v_user FROM dual;
DBMS_SESSION.SET_CONTEXT
(c_context, c_attrib, v_user);
END set_app_context;
FUNCTION the_predicate
(p_schema VARCHAR2, p_name VARCHAR2)
RETURN VARCHAR2
IS
v_context_value VARCHAR2(100) :=
SYS_CONTEXT(c_context, c_attrib);
v_restriction VARCHAR2(2000);
BEGIN
IF v_context_value LIKE 'AM%' THEN
v_restriction :=
'ACCOUNT_MGR_ID =
SYSTOOLS
SUBSTR(''' || v_context_value || ''', 3, 3)';
ELSE
v_restriction := null;
END IF;
RETURN v_restriction;
END the_predicate;
SYSTOOLS
Use the DBMS_RLS package:
• It contains the fine-grained access administrative interface.
• It adds a fine-grained access control policy to a table or
view.
• You use the ADD_POLICY procedure to add a fine-grained
access control policy to a table or view.
Security
SYSTOOLS
policies
ADD_POLICY oe_access_policy
SYSTOOLS
Step 3: Define the Policy
The DBMS_RLS.ADD_POLICY procedure adds a fine-grained access control policy to a table
or view. The procedure causes the current transaction, if any, to commit before the operation is
carried out. However, this does not cause a commit first if it is inside a DDL event trigger. These
are the parameters for the ADD_POLICY procedure:
DBMS_RLS.ADD_POLICY (
object_schema IN VARCHAR2 := NULL,
object_name IN VARCHAR2,
policy_name IN VARCHAR2,
function_schema IN VARCHAR2 := NULL,
policy_function IN VARCHAR2,
statement_types IN VARCHAR2 := NULL,
update_check IN BOOLEAN := FALSE,
enable IN BOOLEAN := TRUE);
SYSTOOLS
Parameter Description
OBJECT_SCHEMA Schema containing the table or view (logon user, if NULL).
OBJECT_NAME Name of the table or view to which the policy is added.
POLICY_NAME Name of the policy to be added. For any table of view, each
POLICY_NAME must be unique.
FUNCTION_SCHEMA Schema of the policy function (logon user, if NULL).
POLICY_FUNCTION Name of the function that generates a predicate for the policy. If the
function is defined within a package, the name of the package must
be present.
STATEMENT_TYPES Statement types that the policy will apply. It can be any combination
of SELECT, INSERT, UPDATE, and DELETE. The default is to
apply all these statement types to the policy.
UPDATE_CHECK Optional argument for the INSERT or UPDATE statement types.
The default is FALSE. Setting update_check to TRUE causes the
SYSTOOLS
server to also check the policy against the value after INSERT or
UPDATE.
ENABLE Indicates whether the policy is enabled when it is added. The default
is TRUE.
The following is a list of the procedures contained in the DBMS_RLS package. For detailed
information, refer to the PL/SQL Packages and Types Reference 11g Release 1 (11.1).
Procedure Description
ADD_POLICY Adds a fine-grained access control policy to a table or view
DROP_POLICY Drops a fine-grained access control policy from a table or view
REFRESH_POLICY Causes all the cached statements associated with the policy to be
reparsed
ENABLE_POLICY Enables or disables a fine-grained access control policy
SYSTOOLS
CREATE_POLICY_GROUP Creates a policy group
ADD_GROUPED_POLICY Adds a policy associated with a policy group
ADD_POLICY_CONTEXT Adds the context for the active application
DELETE_POLICY_GROUP Deletes a policy group
DROP_GROUPED_POLICY Drops a policy associated with a policy group
DROP_POLICY_CONTEXT Drops a driving context from the object so that it has one less
driving context
ENABLE_GROUPED_POLICY Enables or disables a row-level group security policy
REFRESH_GROUPED_POLICY Reparses the SQL statements associated with a refreshed policy
SYSTOOLS
CONNECT /as sysdba
DECLARE
BEGIN
DBMS_RLS.ADD_POLICY (
'OE', Object schema
'CUSTOMERS', Table name
'OE_ACCESS_POLICY', Policy name
'OE', Function schema
'ORDERS_APP_PKG.THE_PREDICATE', Policy function
'SELECT, UPDATE, DELETE', Statement types
SYSTOOLS
FALSE, Update check
TRUE); Enabled
END;
/
SYSTOOLS
This example specifies that whenever a SELECT, UPDATE, or DELETE statement on the
OE.CUSTOMERS table is executed, the predicate function return result is appended to the
WHERE clause.
SYSTOOLS
Create a database trigger that executes whenever anyone logs
on to the database:
CONNECT /as sysdba
SYSTOOLS
/
SYSTOOLS
SYSTOOLS
Data in the CUSTOMERS table:
CONNECT as OE
SELECT COUNT(*), account_mgr_id
FROM customers
GROUP BY account_mgr_id;
COUNT(*) ACCOUNT_MGR_ID
---------- --------------
111 145
76 147
58 148
74 149
1
CONNECT AM148/oracle
SYSTOOLS
SELECT customer_id, customer_last_name
FROM oe.customers;
CUSTOMER_ID CUSTOMER_LAST_NAME
----------- -----------------
...
58 rows selected.
Example Results
The AM148 user who logs on sees only those rows in the CUSTOMERS table that are defined by
the predicate function. The user can issue SELECT, UPDATE, and DELETE statements against
the CUSTOMERS table, but only the rows defined by the predicate function can be manipulated.
UPDATE oe.customers
SET credit_limit = credit_limit + 5000
SYSTOOLS
WHERE customer_id = 101;
0 rows updated.
The AM148 user does not have access to customer ID 101. Customer ID 101 has the account
manager of 145. Any updates, deletes, or selects attempted by user AM148 on customers that do
not have him or her as an account manager are not performed. It is as though these customers do
not exist.
•
•
SYSTOOLS
USER_POLICIES
ALL_POLICIES
• DBA_POLICIES
• ALL_CONTEXT
• DBA_CONTEXT
SYSTOOLS
6 - 23 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
ALL_POLICIES All policies owned or accessible by the current schema
DBA_POLICIES All policies in the database (its columns are the same as those in
ALL_POLICIES)
ALL_CONTEXT All active context namespaces defined in the session
DBA_CONTEXT All context namespace information (active and inactive)
SYSTOOLS
Use ALL_CONTEXT to see the active context namespaces
defined in your session:
CONNECT AS AM148
SELECT *
FROM all_context;
SYSTOOLS
6 - 24 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
OE_ACCESS_POLICY policy.
SELECT object_name, policy_name, pf_owner, package,
function, sel, ins, upd, del
FROM all_policies;
OBJECT_NAME POLICY_NAME
---------------------------- ----------------------------
PF_OWNER PACKAGE
---------------------------- ----------------------------
FUNCTION SEL INS UPD DEL
---------------------------- --- --- --- ---
CUSTOMERS OE_ACCESS_POLICY
OE ORDERS_APP_PKG
THE_PREDICATE YES NO YES YES
SYSTOOLS
• Indicate a set of policies that belong to an application
• Are set up by a DBA through an application context called a
driving context
• Use the DBMS_RLS package to administer the security
policies
SYSTOOLS
ADD_POLICY_GROUP
Policy Groups
Policy groups were introduced in Oracle9i, release 1 (9.0.1). The DBA designates an application
context, called a driving context, to indicate the policy group in effect. When tables or views are
accessed, the fine-grained access control engine looks up the driving context to determine the
policy group in effect and enforces all associated policies that belong to that policy group.
SYSTOOLS
The PL/SQL DBMS_RLS package enables you to administer your security policies and groups.
Using this package, you can add, drop, enable, disable, and refresh the policy groups that you
create.
SYSTOOLS
• SYS_DEFAULT is the default policy group:
– The SYS_DEFAULT group may or may not
contain policies.
– All policies belong to SYS_DEFAULT by default.
– You cannot drop the SYS_DEFAULT policy group.
• Use DBMS_RLS.CREATE_POLICY_GROUP to create a new
group.
• Use DBMS_RLS.ADD_GROUPED_POLICY to add a policy
associated with a policy group.
SYSTOOLS
• You can apply multiple driving contexts to the same table or
view.
SYSTOOLS
group for a particular table or view are always executed along with the policy group specified by
the driving context. The SYS_DEFAULT policy group may or may not contain policies. If you
attempt to drop the SYS_DEFAULT policy group, an error is raised. If you add policies
associated with two or more objects to the SYS_DEFAULT policy group, each such object has a
separate SYS_DEFAULT policy group associated with it.
For example, the CUSTOMERS table in the OE schema has one SYS_DEFAULT policy group,
and the ORDERS table in the OE schema has a different SYS_DEFAULT policy group associated
with it.
SYS_DEFAULT
- policy1 (OE/CUSTOMERS)
- policy3 (OE/CUSTOMERS)
SYS_DEFAULT
- policy2 (OE/ORDERS)
SYSTOOLS
DBMS_RLS.ADD_GROUPED_POLICY interface to specify the group to which the policy
belongs. To specify which policies are effective, you can add a driving context using the
DBMS_RLS.ADD_POLICY_CONTEXT interface. If the driving context returns an unknown
policy group, an error is returned.
If the driving context is not defined, all policies are executed. Likewise, if the driving context is
NULL, the policies from all policy groups are enforced. Thus, an application that accesses the
data cannot bypass the security setup module (that sets up the application context) to avoid
applicable policies.
You can apply multiple driving contexts to the same table or view, and each of them are
processed individually. Thus, you can configure multiple active sets of policies to be enforced.
You can create a new policy by using the DBMS_RLS package either from the command line or
programmatically, or you can access the Oracle Policy Manager graphical user interface in
Oracle Enterprise Manager.
SYSTOOLS
SYSTOOLS
SYSTOOLS
In this lesson, you should have learned how to:
• Describe the process of fine-grained access control
• Implement and test fine-grained access control
Context
Implements
Attribute Value
Attached Associated
Security
to a with a
Session policies
SYSTOOLS
session package
Summary
In this lesson, you should have learned about fine-grained access control and the steps required
to implement a virtual private database.
SYSTOOLS
SYSTOOLS
This practice covers the following topics:
• Creating an application context
• Creating a policy
• Creating a logon trigger
• Implementing a virtual private database
• Testing the virtual private database
SYSTOOLS
6 - 29 Copyright © 2008, Oracle. All rights reserved.
Practice 6: Overview
In this practice, you implement and test fine-grained access control.
SYSTOOLS
SYSTOOLS
policy: “Sales Representatives can see only their own order information in the ORDERS table.”
You create sales representative IDs to test the success of your implementation.
Examine the definition of the ORDERS table and the ORDER count for each sales representative:
DESCRIBE orders
Name Null? Type
------------------ -------- --------------------------------
ORDER_ID NOT NULL NUMBER(12)
ORDER_DATE NOT NULL TIMESTAMP(6) WITH LOCAL TIME ZONE
ORDER_MODE VARCHAR2(8)
CUSTOMER_ID NOT NULL NUMBER(6)
ORDER_STATUS NUMBER(2)
ORDER_TOTAL NUMBER(8,2)
SALES_REP_ID NUMBER(6)
PROMOTION_ID NUMBER(6)
SYSTOOLS
SELECT sales_rep_id, count(*)
FROM orders
GROUP BY sales_rep_id;
SALES_REP_ID COUNT(*)
------------ ----------
153 5
154 10
155 5
156 5
158 7
159 7
160 6
161 13
163 12
SYSTOOLS
35
10 rows selected.
1. Use your OE connection. Examine and then run the lab_06_01.sql script.
This script creates the sales representative ID accounts with appropriate privileges to access
the database.
SYSTOOLS
a. Examine this package specification:
CREATE OR REPLACE PACKAGE sales_orders_pkg
IS
PROCEDURE set_app_context;
FUNCTION the_predicate
(p_schema VARCHAR2, p_name VARCHAR2)
RETURN VARCHAR2;
END sales_orders_pkg; -- package spec
/
b. Create this package specification and the package body in the OE schema.
c. When you create the package body, set up two constants as follows:
c_context CONSTANT VARCHAR2(30) := 'SALES_ORDERS_CTX';
c_attrib CONSTANT VARCHAR2(30) := 'SALES_REP';
d. Use these constants in the SET_APP_CONTEXT procedure to set the application
context to the current user.
SYSTOOLS
4. Connect as SYSDBA and define the policy.
a. Use DBMS_RLS.ADD_POLICY to define the policy.
b. Use these specifications for the parameter values:
object_schema OE
object_name ORDERS
policy_name OE_ORDERS_ACCESS_POLICY
function_schema OE
policy_function SALES_ORDERS_PKG.THE_PREDICATE
statement_types SELECT, INSERT, UPDATE, DELETE
update_check FALSE,
enable TRUE);
5. Connect as SYSDBA and create a logon trigger to implement fine-grained access control.
You can call the trigger SET_ID_ON_LOGON. This trigger causes the context to be set as
each user is logged on.
SYSTOOLS
SYSTOOLS
ORDERS table. For example, your results should match:
CONNECT sr153/oracle
SALES_REP_ID COUNT(*)
------------ ----------
153 5
CONNECT sr154/oracle
SYSTOOLS
GROUP BY sales_rep_id;
SALES_REP_ID COUNT(*)
------------ ----------
154 10
Note
During debugging, you may need to disable or remove some of the objects created for this
lesson.
• If you need to disable the logon trigger, issue this command:
ALTER TRIGGER set_id_on_logon DISABLE;
• If you need to remove the policy that you created, issue this command:
EXECUTE DBMS_RLS.DROP_POLICY('OE', 'ORDERS', -
'OE_ORDERS_ACCESS_POLICY')
SYSTOOLS
SYSTOOLS
Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Objectives
SYSTOOLS
After completing this lesson, you should be able to do the
following:
• Compare and contrast LONG and large object (LOB) data
types
• Create and maintain LOB data types
• Differentiate between internal and external LOBs
• Use the DBMS_LOB PL/SQL package
• Describe the use of temporary LOBs
SYSTOOLS
7-2 Copyright © 2008, Oracle. All rights reserved.
Objectives
Databases have long been used to store large objects. However, the mechanisms built into
databases have never been as useful as the large object (LOB) data types that have been provided
since Oracle8. This lesson describes the characteristics of the new data types, comparing and
contrasting them with the earlier data types. Examples, syntax, and issues regarding the LOB
SYSTOOLS
types are also presented.
Note: A LOB is a data type and should not be confused with an object type.
•
•
SYSTOOLS
Introduction to LOBs
Managing BFILEs by using the DBMS_LOB package
• Migrating LONG data types to LOBs
• Manipulating LOB data
• Using temporary LOBs
SYSTOOLS
7-3 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
LOBs are used to store large, unstructured data such as text,
graphic images, films, and sound waveforms.
SYSTOOLS
forth upon this continent, a
new nation, conceived in
LIBERTY, and dedicated to the
proposition that all men are
created equal.” Movie (BFILE)
LOB: Overview
A LOB is a data type that is used to store large, unstructured data such as text, graphic images,
video clippings, and so on. Structured data, such as a customer record, may be a few hundred
bytes large, but even small amounts of multimedia data can be thousands of times larger. Also,
multimedia data may reside in operating system (OS) files, which may need to be accessed from
SYSTOOLS
a database.
There are four large object data types:
• BLOB represents a binary large object, such as a video clip.
• CLOB represents a character large object.
• NCLOB represents a multiple-byte character large object.
• BFILE represents a binary file stored in an OS binary file outside the database. The BFILE
column or attribute stores a file locator that points to the external file.
LOBs are characterized in two ways, according to their interpretations by the Oracle server
(binary or character) and their storage aspects. LOBs can be stored internally (inside the
database) or in host files. There are two categories of LOBs:
• Internal LOBs (CLOB, NCLOB, BLOB): Stored in the database
• External files (BFILE): Stored outside the database
SYSTOOLS
The other implicit conversions between LOBs are not possible. For example, if the user creates a
table T with a CLOB column and a table S with a BLOB column, the data is not directly
transferable between these two columns.
BFILEs can be accessed only in read-only mode from an Oracle server.
SYSTOOLS
SYSTOOLS
SYSTOOLS
LONG and LONG RAW LOB
Single LONG column per table Multiple LOB columns per table
Up to 2 GB Up to 4 GB
SYSTOOLS
7-6 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
• A table can have multiple LOB columns and object type attributes. A table can have only
one LONG column.
• The maximum size of LONGs is 2 GB; LOBs can be up to 4 GB.
• LOBs return the locator; LONGs return the data.
• LOBs store a locator in the table and the data in a different segment, unless the data is less
than 4,000 bytes; LONGs store all data in the same data block. In addition, LOBs allow data
to be stored in a separate segment and tablespace, or in a host file.
• LOBs can be object type attributes; LONGs cannot be object type attributes.
• LOBs support random piecewise access to the data through a file-like interface; LONGs are
restricted to sequential piecewise access.
The TO_LOB function can be used to convert LONG and LONG RAW values in a column to LOB
values. You use this in the SELECT list of a subquery in an INSERT statement.
SYSTOOLS
The LOB column stores a locator to the LOB’s value.
LOB locator
SYSTOOLS
of a table
Components of a LOB
There are two parts to a LOB:
• LOB value: The data that constitutes the real object being stored
• LOB locator: A pointer to the location of the LOB value that is stored in the database
Regardless of where the LOB value is stored, a locator is stored in the row. You can think of a
SYSTOOLS
LOB locator as a pointer to the actual location of the LOB value.
A LOB column does not contain the data; it contains the locator of the LOB value.
When a user creates an internal LOB, the value is stored in the LOB segment and a locator to the
out-of-line LOB value is placed in the LOB column of the corresponding row in the table.
External LOBs store the data outside the database, so only a locator to the LOB value is stored in
the table.
To access and manipulate LOBs without SQL data manipulation language (DML), you must
create a LOB locator. The programmatic interfaces operate on the LOB values by using these
locators in a manner similar to OS file handles.
SYSTOOLS
The LOB value is stored in the database.
SYSTOOLS
are created equal.”
CLOB BLOB
Internal LOBs
An internal LOB is stored in the Oracle server. A BLOB, NCLOB, or CLOB can be one of the
following:
• An attribute of a user-defined type
• A column in a table
SYSTOOLS
• A bind or host variable
• A PL/SQL variable, parameter, or result
Internal LOBs can take advantage of Oracle features, such as:
• Concurrency mechanisms
• Redo logging and recovery mechanisms
• Transactions with COMMIT or ROLLBACK
The BLOB data type is interpreted by the Oracle server as a bitstream, similar to the LONG RAW
data type.
The CLOB data type is interpreted as a single-byte character stream.
The NCLOB data type is interpreted as a multiple-byte character stream, based on the byte length
of the database national character set.
SYSTOOLS
• To interact fully with LOB, file-like interfaces are provided in:
– PL/SQL package DBMS_LOB
– Oracle Call Interface (OCI)
– Oracle Objects for object linking and embedding (OLE)
– Pro*C/C++ and Pro*COBOL precompilers
– Java Database Connectivity (JDBC)
• The Oracle server provides some support for LOB
management through SQL.
SYSTOOLS
7-9 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
OLE, Oracle precompilers, or JDBC by using the LOB locator as a reference to the LOB
value. You can also manage LOBs through SQL.
5. Use the COMMIT command to make any changes permanent.
•
•
SYSTOOLS
Introduction to LOBs
Managing BFILEs by using the DBMS_LOB package
• Migrating LONG data types to LOBs
• Manipulating LOB data
• Using temporary LOBs
SYSTOOLS
7 - 10 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
The BFILE data type supports an external or file-based large
object as:
• Attributes in an object type
• Column values in a table
SYSTOOLS
system. Oracle Database 10g provides:
• Definition of BFILE objects
• Association of BFILE objects with the corresponding external files
• Security for BFILEs
The remaining operations that are required for using BFILEs are possible through the
DBMS_LOB package and OCI. BFILEs are read-only; they do not participate in transactions.
Support for integrity and durability must be provided by the operating system. The file must be
created and placed in the appropriate directory, giving the Oracle process privileges to read the
file. When the LOB is deleted, the Oracle server does not delete the file. Administration of the
files and the OS directory structures can be managed by the DBA, system administrator, or user.
The maximum size of an external large object depends on the operating system but cannot
exceed 4 GB.
Note: BFILEs are available with the Oracle8 database and later releases.
SYSTOOLS
User
Access
permissions
Securing BFILEs
Unauthenticated access to files on a server presents a security risk. Oracle Database 10g can act
as a security mechanism to shield the operating system from unsecured access while removing
the need to manage additional user accounts on an enterprise computer system.
File Location and Access Privileges
SYSTOOLS
The file must reside on the machine where the database exists. A timeout to read a nonexistent
BFILE is based on the OS value.
You can read a BFILE in the same way that you read an internal LOB. However, there could be
restrictions related to the file itself, such as:
• Access permissions
• File system space limits
• Non-Oracle manipulations of files
• OS maximum file size
Oracle Database 10g does not provide transactional support on BFILEs. Any support for
integrity and durability must be provided by the underlying file system and the OS. Oracle
backup and recovery methods support only the LOB locators, not the physical BFILEs.
SYSTOOLS
User
DIRECTORY
LOB_PATH =
'/oracle/lob/'
What Is a DIRECTORY?
A DIRECTORY is a nonschema database object that enables the administration of access and
usage of BFILEs in Oracle Database 10g.
A DIRECTORY specifies an alias for a directory on the file system of the server under which a
BFILE is located. By granting users suitable privileges for these items, you can provide secure
SYSTOOLS
access to files in the corresponding directories on a user-by-user basis (certain directories can be
made read-only, inaccessible, and so on).
Furthermore, these directory aliases can be used while referring to files (open, close, read, and so
on) in PL/SQL and OCI. This provides application abstraction from hard-coded path names and
gives flexibility in portably managing file locations.
The DIRECTORY object is owned by SYS and created by the DBA (or a user with the CREATE
ANY DIRECTORY privilege). The directory objects have object privileges, unlike other
nonschema objects. Privileges to the DIRECTORY object can be granted and revoked. Logical
path names are not supported.
The permissions for the actual directory depend on the operating system. They may differ from
those defined for the DIRECTORY object and could change after creation of the DIRECTORY
object.
SYSTOOLS
read the file.
SYSTOOLS
these files could corrupt the database. Currently, only the READ privilege can be given for a
DIRECTORY object.
• The CREATE ANY DIRECTORY and DROP ANY DIRECTORY system privileges should be
used carefully and not granted to users indiscriminately.
• DIRECTORY objects are not schema objects; all are owned by SYS.
• Create the directory paths with appropriate permissions on the OS before creating the
DIRECTORY object. Oracle does not create the OS path.
If you migrate the database to a different OS, you may need to change the path value of the
DIRECTORY object.
Information about the DIRECTORY object that you create by using the CREATE DIRECTORY
command is stored in the DBA_DIRECTORIES and ALL_DIRECTORIES data dictionary
views.
SYSTOOLS
• Working with LOBs often requires the use of the Oracle-
supplied DBMS_LOB package.
• DBMS_LOB provides routines to access and manipulate
internal and external LOBs.
• LOB data can be retrieved directly using SQL.
• In PL/SQL, you can define a VARCHAR2 for a CLOB and a
RAW for a BLOB.
SYSTOOLS
7 - 15 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
The two constants, LOBMAXSIZE and FILE_READONLY, that are defined in the package
specification are also used in the procedures and functions of DBMS_LOB; for example, use
them to achieve the maximum level of purity in SQL expressions.
The DBMS_LOB functions and procedures can be broadly classified into two types: mutators and
observers.
• The mutators can modify LOB values: APPEND, COPY, ERASE, TRIM, WRITE,
FILECLOSE, FILECLOSEALL, and FILEOPEN.
• The observers can read LOB values: COMPARE, FILEGETNAME, INSTR, GETLENGTH,
READ, SUBSTR, FILEEXISTS, and FILEISOPEN.
SYSTOOLS
• Modify LOB values:
APPEND, COPY, ERASE, TRIM, WRITE, LOADFROMFILE
• Read or examine LOB values:
GETLENGTH, INSTR, READ, SUBSTR
• Specific to BFILEs:
FILECLOSE, FILECLOSEALL, FILEEXISTS,
FILEGETNAME, FILEISOPEN, FILEOPEN
SYSTOOLS
7 - 16 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
TRIM Trims the LOB value to a specified shorter length
WRITE Writes data to the LOB from a specified offset
GETLENGTH Gets the length of the LOB value
INSTR Returns the matching position of the nth occurrence of the pattern in the LOB
READ Reads data from the LOB starting at the specified offset
SUBSTR Returns part of the LOB value starting at the specified offset
FILECLOSE Closes the file
FILECLOSEALL Closes all previously opened files
FILEEXISTS Checks whether the file exists on the server
FILEGETNAME Gets the directory alias and the file name
FILEISOPEN Checks whether the file was opened using the input BFILE locators
FILEOPEN Opens a file
SYSTOOLS
• NULL parameters get NULL returns.
• Offsets:
– BLOB, BFILE: Measured in bytes
– CLOB, NCLOB: Measured in characters
• There are no negative values for parameters.
SYSTOOLS
7 - 17 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
from the beginning of the LOB data from which to start the operation. The negative offsets and
ranges that are observed in SQL string functions and operators are not allowed. Corresponding
exceptions are raised upon violation. The default value for an offset is 1, which indicates the first
byte or character in the LOB value.
Similarly, only natural number values are allowed for the amount (BUFSIZ) parameter.
Negative values are not allowed.
SYSTOOLS
PROCEDURE READ (
lobsrc IN BFILE|BLOB|CLOB ,
amount IN OUT BINARY_INTEGER,
offset IN INTEGER,
buffer OUT RAW|VARCHAR2 )
PROCEDURE WRITE (
lobdst IN OUT BLOB|CLOB,
SYSTOOLS
amount IN OUT BINARY_INTEGER,
offset IN INTEGER := 1,
buffer IN RAW|VARCHAR2 ) -- RAW for BLOB
DBMS_LOB.READ
Call the READ procedure to read and return piecewise a specified AMOUNT of data from a given
LOB, starting from OFFSET. An exception is raised when no more data remains to be read from
the source LOB. The value returned in AMOUNT is less than the one specified if the end of the
LOB is reached before the specified number of bytes or characters can be read. In the case of
CLOBs, the character set of data in BUFFER is the same as that in the LOB.
SYSTOOLS
PL/SQL allows a maximum length of 32,767 for RAW and VARCHAR2 parameters. Ensure that
the allocated system resources are adequate to support buffer sizes for the given number of user
sessions. Otherwise, the Oracle server raises the appropriate memory exceptions.
Note: BLOB and BFILE return RAW; the others return VARCHAR2.
DBMS_LOB.WRITE
Call the WRITE procedure to write piecewise a specified AMOUNT of data into a given LOB,
from the user-specified BUFFER, starting from an absolute OFFSET from the beginning of the
LOB value.
Make sure (especially with multiple-byte characters) that the amount in bytes corresponds to the
amount of buffer data. WRITE has no means of checking whether they match, and it will write
AMOUNT bytes of the buffer contents into the LOB.
SYSTOOLS
The DBA or the system administrator:
1. Creates an OS directory and supplies files
2. Creates a DIRECTORY object in the database
3. Grants the READ privilege on the DIRECTORY object to the
appropriate database users
The developer or the user:
4. Creates an Oracle table with a column that is defined as a
BFILE data type
5. Inserts rows into the table by using the BFILENAME
SYSTOOLS
function to populate the BFILE column
6. Writes a PL/SQL subprogram that declares and initializes a
LOB locator, and reads BFILE
Managing BFILEs
Managing BFILEs requires cooperation between the database administrator and the system
administrator, and then between the developer and the user of the files.
The database or system administrator must perform the following privileged tasks:
1. Create the operating system (OS) directory (as an Oracle user), and set permissions so that
SYSTOOLS
the Oracle server can read the contents of the OS directory. Load files into the OS directory.
2. Create a database DIRECTORY object that references the OS directory.
3. Grant the READ privilege on the database DIRECTORY object to the database users that
require access to it.
The designer, application developer, or user must perform the following tasks:
4. Create a database table containing a column that is defined as the BFILE data type.
5. Insert rows into the table by using the BFILENAME function to populate the BFILE
column, associating the field to an OS file in the named DIRECTORY.
6. Write PL/SQL subprograms that:
a. Declare and initialize the BFILE LOB locator
b. Select the row and column containing the BFILE into the LOB locator
c. Read the BFILE with a DBMS_LOB function, by using the locator file reference
SYSTOOLS
1. Create an OS directory to store the physical data files:
md D:\Labs\DATA_FILES\MEDIA_FILES
SYSTOOLS
GRANT READ ON DIRECTORY data_files TO OE;
SYSTOOLS
Use the CREATE DIRECTORY command to specify the pointer to the location where your
BFILEs are stored. You need the CREATE ANY DIRECTORY privilege.
Syntax definition: CREATE DIRECTORY dir_name AS os_path;
In this syntax, dir_name is the name of the directory database object, and os_path specifies
the location of the BFILEs.
The slide examples show the commands to set up:
• The physical directory (for example, /temp/data_files) in the OS
• A named DIRECTORY object, called data_files, that points to the physical directory in
the OS
• The READ access right on the directory to be granted to users in the database that provides
the privilege to read the BFILEs from the directory
Note: The value of the SESSION_MAX_OPEN_FILES database initialization parameter, which
is set to 10 by default, limits the number of BFILEs that can be opened in a session.
SYSTOOLS
• Use the BFILENAME function to initialize a BFILE column.
The function syntax is:
FUNCTION BFILENAME(directory_alias IN VARCHAR2,
filename IN VARCHAR2)
RETURN BFILE;
• Example:
– Add a BFILE column to a table:
ALTER TABLE customers ADD video BFILE;
SYSTOOLS
UPDATE customers
SET video = BFILENAME('DATA_FILES', 'Winters.avi')
WHERE customer_id = 448;
SYSTOOLS
The BFILENAME function creates a pointer (or LOB locator) to the external file stored in a
physical directory, which is assigned a directory alias name that is used in the first parameter of
the function. Populate the BFILE column by using the BFILENAME function in either of the
following:
• The VALUES clause of an INSERT statement
• The SET clause of an UPDATE statement
An UPDATE operation can be used to change the pointer reference target of the BFILE. A
BFILE column can also be initialized to a NULL value and updated later with the BFILENAME
function, as shown in the slide.
After the BFILE columns are associated with a file, subsequent read operations on the BFILE
can be performed by using the PL/SQL DBMS_LOB package and OCI. However, these files are
read-only when accessed through BFILEs. Therefore, they cannot be updated or deleted through
BFILEs.
SYSTOOLS
CREATE PROCEDURE set_video(
dir_alias VARCHAR2, custid NUMBER) IS
filename VARCHAR2(40);
file_ptr BFILE;
CURSOR cust_csr IS
SELECT cust_first_name FROM customers
WHERE customer_id = custid FOR UPDATE;
BEGIN
FOR rec IN cust_csr LOOP
filename := rec.cust_first_name || '.gif';
file_ptr := BFILENAME(dir_alias, filename);
DBMS_LOB.FILEOPEN(file_ptr);
UPDATE customers SET video = file_ptr
SYSTOOLS
WHERE CURRENT OF cust_csr;
DBMS_OUTPUT.PUT_LINE('FILE: ' || filename ||
' SIZE: ' || DBMS_LOB.GETLENGTH(file_ptr));
DBMS_LOB.FILECLOSE(file_ptr);
END LOOP;
END set_video;
SYSTOOLS
• Creates an in-memory LOB locator for the BFILE in the file_ptr variable
• Calls the DBMS_LOB.FILEOPEN procedure to verify whether the file exists, and to
determine the size of the file by using the DBMS_LOB.GETLENGTH function
• Executes an UPDATE statement to write the BFILE locator value to the video BFILE
column
• Displays the file size returned from the DBMS_LOB.GETLENGTH function
• Closes the file by using the DBMS_LOB.FILECLOSE procedure
Suppose that you execute the following call:
EXECUTE set_video('DATA_FILES', 844)
The sample result is:
FILE: Alice.gif SIZE: 2619802
SYSTOOLS
The DBMS_LOB.FILEEXISTS function can check whether the
file exists in the OS. The function:
• Returns 0 if the file does not exist
• Returns 1 if the file does exist
CREATE OR REPLACE FUNCTION get_filesize(p_file_ptr IN
OUT BFILE)
RETURN NUMBER IS
v_file_exists BOOLEAN;
v_length NUMBER:= -1;
BEGIN
v_file_exists := DBMS_LOB.FILEEXISTS(p_file_ptr) = 1;
IF v_file_exists THEN
DBMS_LOB.FILEOPEN(p_file_ptr);
SYSTOOLS
v_length := DBMS_LOB.GETLENGTH(p_file_ptr);
DBMS_LOB.FILECLOSE(p_file_ptr);
END IF;
RETURN v_length;
END;
/
SYSTOOLS
• A value 0 if the physical file does not exist
• A value 1 if the physical file exists
If the BFILE parameter is invalid, one of the following three exceptions may be raised:
• NOEXIST_DIRECTORY if the directory does not exist
• NOPRIV_DIRECTORY if the database processes do not have privileges for the directory
• INVALID_DIRECTORY if the directory was invalidated after the file was opened
•
•
SYSTOOLS
Introduction to LOBs
Managing BFILEs by using the DBMS_LOB package
• Migrating LONG data types to LOBs
• Manipulating LOB data
• Using temporary LOBs
SYSTOOLS
7 - 24 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
Oracle Database 10g enables the migration of LONG columns to
LOB columns.
• Data migration consists of the procedure to move existing
tables containing LONG columns to use LOBs:
ALTER TABLE [<schema>.] <table_name>
MODIFY (<long_col_name> {CLOB | BLOB | NCLOB})
SYSTOOLS
7 - 25 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
The constraints of the LONG column (NULL and NOT NULL are the only allowed constraints) are
maintained for the new LOB columns. The default value specified for the LONG column is also
copied to the new LOB column. For example, you have the following table:
CREATE TABLE long_tab (id NUMBER, long_col LONG);
To change the long_col column in the long_tab table to the CLOB data type, use:
ALTER TABLE long_tab MODIFY (long_col CLOB );
For information about the limitations on LONG-to-LOB migration, refer to Oracle Database
Application Developer’s Guide - Large Objects. In application migration, the existing LONG
applications change to using LOBs. You can use SQL and PL/SQL to access LONGs and LOBs.
The LONG-to-LOB migration API is provided for both OCI and PL/SQL.
SYSTOOLS
• Implicit conversion: From LONG (LONG RAW) or a
VARCHAR2(RAW) variable to a CLOB (BLOB) variable, and
vice versa.
• Explicit conversion:
– TO_CLOB() converts LONG, VARCHAR2, and CHAR to CLOB.
– TO_BLOB() converts LONG RAW and RAW to BLOB.
• Function and procedure parameter passing:
– CLOBs and BLOBs are passed as actual parameters.
– VARCHAR2, LONG, RAW, and LONG RAW are formal parameters,
and vice versa.
SYSTOOLS
• LOB data is acceptable in most of the SQL and PL/SQL
operators and built-in functions.
SYSTOOLS
vice versa.
Explicit conversion functions: In PL/SQL, the following two new explicit conversion functions
were added in Oracle Database 10g to convert other data types to CLOB and BLOB as part of the
LONG-to-LOB migration:
• TO_CLOB()converts LONG, VARCHAR2, and CHAR to CLOB.
• TO_BLOB()converts LONG RAW and RAW to BLOB.
•
•
SYSTOOLS
Introduction to LOBs
Managing BFILEs by using the DBMS_LOB package
• Migrating LONG data types to LOBs
• Manipulating LOB data
• Using temporary LOBs
SYSTOOLS
7 - 27 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• Add the LOB columns to an existing table by using ALTER
TABLE.
ALTER TABLE customers
ADD (resume CLOB, picture BLOB);
• Create a tablespace where you will put a new table with the
LOB columns.
connect /as sysdba
SYSTOOLS
EXTENT MANAGEMENT LOCAL
UNIFORM SIZE 64M
SEGMENT SPACE MANAGEMENT AUTO;
SYSTOOLS
• EMPTY_BLOB() function to a LOB locator for a BLOB column
Note: These functions create the LOB locator value and not the LOB content. In general, you use
the DBMS_LOB package subroutines to populate the content. The functions are available in
Oracle SQL DML, and are not part of the DBMS_LOB package.
LOB columns are defined by using SQL data definition language (DDL). You can add LOB
columns to an existing table by using the ALTER TABLE statement.
You can also add LOB columns to a new table. It is recommended that you create a tablespace
first, and then create the new table in that tablespace.
SYSTOOLS
Initialize the column LOB locator value with the DEFAULT option
or the DML statements using:
• EMPTY_CLOB() function for a CLOB column
• EMPTY_BLOB() function for a BLOB column
connect oe
SYSTOOLS
picture BLOB DEFAULT EMPTY_BLOB())
LOB(picture) STORE AS BASICFILE
(TABLESPACE lob_tbs1);
SYSTOOLS
The CUSTOMER_PROFILES table is created. The PICTURE column holds the LOB data in the
BasicFile format, because the storage clause identifies the format. You learn about the
SecureFile format in the lesson titled “Administering SecureFile LOBs.”
You learn how to use these functions in INSERT and UPDATE statements to initialize the LOB
locator values.
SYSTOOLS
• Insert a row into a table with LOB columns:
INSERT INTO customer_profiles
(id, full_name, resume, picture)
VALUES (164, 'Charlotte Kazan', EMPTY_CLOB(), NULL);
SYSTOOLS
UPDATE customer_profiles
SET resume = 'Date of Birth: 1 June 1956'
WHERE id = 150;
SYSTOOLS
empty or populated LOB value. This is done by using the EMPTY_BLOB()and
EMPTY_CLOB() functions.
2. Populate the LOB contents by using the DBMS_LOB package routines.
However, as shown in the slide examples, the two UPDATE statements initialize the resume
LOB locator value and populate its contents by supplying a literal value. This can also be done in
an INSERT statement. A LOB column can be updated to:
• Another LOB value
• A NULL value
• A LOB locator with empty contents by using the EMPTY_*LOB() built-in function
You can update the LOB by using a bind variable in embedded SQL. When assigning one LOB
to another, a new copy of the LOB value is created. Use a SELECT FOR UPDATE statement to
lock the row containing the LOB column before updating a piece of the LOB contents.
SYSTOOLS
• Create the procedure to read the MS Word files and load
them into the LOB column.
• Call this procedure from the WRITE_LOB procedure (shown
on the next page).
SYSTOOLS
BEGIN
DBMS_LOB.OPEN(v_src_loc, DBMS_LOB.LOB_READONLY);
v_amount := DBMS_LOB.GETLENGTH(v_src_loc);
DBMS_LOB.LOADFROMFILE(p_dest_loc, v_src_loc, v_amount);
DBMS_LOB.CLOSE(v_src_loc);
END loadLOBFromBFILE_proc;
SYSTOOLS
The LOADLOBFROMBFILE_PROC procedure is used to read the LOB data into the PICTURE
column in the CUSTOMER_PROFILES table.
In this example:
• DBMS_LOB.OPEN is used to open an external LOB in read-only mode.
• DBMS_LOB.GETLENGTH is used to find the length of the LOB value.
• DBMS_LOB.LOADFROMFILE is used to load the BFILE data into an internal LOB.
• DBMS_LOB.CLOSE is used to close the external LOB.
Note: The LOADLOBFROMBFILE_PROC procedure shown in the slide can be used to read both
SecureFile and BasicFile formats. SecureFile LOBs is discussed in the lesson titled
“Administering SecureFile LOBs.”
SYSTOOLS
Create the procedure to insert LOBs into the table:
CREATE OR REPLACE PROCEDURE write_lob
(p_file IN VARCHAR2, p_dir IN VARCHAR2)
IS
i NUMBER; v_fn VARCHAR2(15);
v_ln VARCHAR2(40); v_b BLOB;
BEGIN
DBMS_OUTPUT.ENABLE;
DBMS_OUTPUT.PUT_LINE('Begin inserting rows...');
FOR i IN 1 .. 30 LOOP
v_fn:=SUBSTR(p_file,1,INSTR(p_file,'.')-1);
v_ln:=SUBSTR(p_file,INSTR(p_file,'.')+1,LENGTH(p_file)-
INSTR(p_file,'.')-4);
INSERT INTO customer_profiles
SYSTOOLS
VALUES (i, v_fn, v_ln, EMPTY_BLOB())
RETURNING picture INTO v_b;
loadLOBFromBFILE_proc(v_b,p_file, p_dir);
DBMS_OUTPUT.PUT_LINE('Row '|| i ||' inserted.');
END LOOP;
COMMIT;
END write_lob;
SYSTOOLS
LOADLOBFROMBFILE routine is then called and the LOB column value is inserted.
The write and read performance statistics for LOB storage is captured through output messages.
SYSTOOLS
1
set serveroutput on
set verify on
set term on
set linesize 200
SYSTOOLS
timing start load_data 2
execute write_lob('karl.brimmer.doc', 'RESUME_FILES')
execute write_lob('monica.petera.doc', 'RESUME_FILES')
execute write_lob('david.sloan.doc', 'RESUME_FILES')
timing stop
SYSTOOLS
available in SQL Developer.
SYSTOOLS
timing start load_data
execute write_lob('karl.brimmer.doc', 'RESUME_FILES');
Begin inserting rows...
Row 1 inserted.
...
PL/SQL procedure successfully completed.
SYSTOOLS
...
PL/SQL procedure successfully completed.
timing stop
timing for: load_data
Elapsed: 00:00:00.96
SYSTOOLS
Create
CREATE OR
IS
SYSTOOLS
the procedure
REPLACE to read
PROCEDURE LOBs from the table:
read_lob
v_lob_loc BLOB;
CURSOR profiles_cur IS
SELECT id, full_name, resume, picture
FROM customer_profiles;
v_profiles_rec customer_profiles%ROWTYPE;
BEGIN
OPEN profiles_cur;
LOOP
FETCH profiles_cur INTO v_profiles_rec;
v_lob_loc := v_profiles_rec.picture;
DBMS_OUTPUT.PUT_LINE('The length is: '||
DBMS_LOB.GETLENGTH(v_lob_loc));
DBMS_OUTPUT.PUT_LINE('The ID is: '|| v_profiles_rec.id);
SYSTOOLS
DBMS_OUTPUT.PUT_LINE('The blob is read: '||
UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(v_lob_loc,200,1)));
EXIT WHEN profiles_cur%NOTFOUND;
END LOOP;
CLOSE profiles_cur;
END;
SYSTOOLS
timing start read_data
execute read_lob;
timing stop
The commands shown in the slide read back the 90 records from the CUSTOMER_PROFILES
table. For each record, the size of the LOB value plus the first 200 characters of the LOB are
displayed on the screen. A SQL*Plus timer is started to capture the total elapsed time for the
retrieval.
SYSTOOLS
The ID is: 1
The blob is read: ¿ ¿ ¿ > ¿¿
x z ¿¿¿¿ w
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿
The length is: 64000
The ID is: 2
The blob is read: ¿ ¿ ¿ > ¿¿
x z ¿¿¿¿ w
...
The length is: 37376
The ID is: 30
The blob is read: ¿ ¿ ¿ > ¿¿
D F ¿¿¿¿ C
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿
SYSTOOLS
The length is: 37376
The ID is: 30
The blob is read: ¿ ¿ ¿ > ¿¿
D F ¿¿¿¿ C
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿
timing stop
timing for: read_data
Elapsed: 00:00:01.09
SYSTOOLS
Note: The text shown on this page is intentional. The text appears as gibberish, because it is a
binary file.
DECLARE
SYSTOOLS
v_lobloc CLOB; -- serves as the LOB locator
v_text VARCHAR2(50) := 'Resigned = 5 June 2000';
v_amount NUMBER ; -- amount to be written
v_offset INTEGER; -- where to start writing
BEGIN
SELECT resume INTO v_lobloc FROM customer_profiles
WHERE id = 164 FOR UPDATE;
v_offset := DBMS_LOB.GETLENGTH(v_lobloc) + 2;
v_amount := length(v_text);
DBMS_LOB.WRITE (v_lobloc, v_amount, v_offset, v_text);
v_text := ' Resigned = 30 September 2000';
SELECT resume INTO v_lobloc FROM customer_profiles
SYSTOOLS
WHERE id = 150 FOR UPDATE;
v_amount := length(v_text);
DBMS_LOB.WRITEAPPEND(v_lobloc, v_amount, v_text);
COMMIT;
END;
SYSTOOLS
The example shows how to fetch a CLOB column in releases before Oracle9i. In those releases,
it was not possible to fetch a CLOB column directly into a character column. The column value
must be bound to a LOB locator, which is accessed by the DBMS_LOB package. An example
later in this lesson shows that you can directly fetch a CLOB column by binding it to a character
variable.
IS
SYSTOOLS
CREATE OR REPLACE PROCEDURE check_space
l_fs1_bytes NUMBER;
l_fs2_bytes NUMBER; ...
BEGIN
DBMS_SPACE.SPACE_USAGE(
segment_owner => 'OE',
segment_name => 'CUSTOMER_PROFILES',
segment_type => 'TABLE',
fs1_bytes => l_fs1_bytes,
fs1_blocks => l_fs1_blocks,
fs2_bytes => l_fs2_bytes,
fs2_blocks => l_fs2_blocks, ...
);
DBMS_OUTPUT.ENABLE;
DBMS_OUTPUT.PUT_LINE(' FS1 Blocks = '||l_fs1_blocks||'
SYSTOOLS
Bytes = '||l_fs1_bytes);
DBMS_OUTPUT.PUT_LINE(' FS2 Blocks = '||l_fs2_blocks||'
Bytes = '||l_fs2_bytes); …
DBMS_OUTPUT.PUT_LINE('=======================================');
DBMS_OUTPUT.PUT_LINE('Total Blocks =
'||to_char(l_fs1_blocks + l_fs2_blocks …));
END;
/
SYSTOOLS
EXECUTE check_space
The output is as follows:
FS1 Blocks = 1 Bytes = 8192
FS2 Blocks = 0 Bytes = 0
FS3 Blocks = 1 Bytes = 8192
FS4 Blocks = 3 Bytes = 24576
Full Blocks = 0 Bytes = 0
=========================
Total Blocks = 5 ||
Total Bytes = 40960
PL/SQL procedure successfully completed.
SYSTOOLS
CREATE OR REPLACE PROCEDURE check_space
IS
l_fs1_bytes NUMBER; l_fs2_bytes NUMBER;
l_fs3_bytes NUMBER; l_fs4_bytes NUMBER;
l_fs1_blocks NUMBER; l_fs2_blocks NUMBER;
l_fs3_blocks NUMBER; l_fs4_blocks NUMBER;
l_full_bytes NUMBER; l_full_blocks NUMBER;
l_unformatted_bytes NUMBER;
l_unformatted_blocks NUMBER;
BEGIN
DBMS_SPACE.SPACE_USAGE(
segment_owner => 'OE',
segment_name => 'CUSTOMER_PROFILES',
segment_type => 'TABLE',
fs1_bytes => l_fs1_bytes,
fs1_blocks => l_fs1_blocks,
SYSTOOLS
fs2_bytes => l_fs2_bytes,
fs2_blocks => l_fs2_blocks,
fs3_bytes => l_fs3_bytes,
fs3_blocks => l_fs3_blocks,
fs4_bytes => l_fs4_bytes,
fs4_blocks => l_fs4_blocks,
full_bytes => l_full_bytes,
full_blocks => l_full_blocks,
unformatted_blocks => l_unformatted_blocks,
unformatted_bytes => l_unformatted_bytes
);
DBMS_OUTPUT.ENABLE;
DBMS_OUTPUT.PUT_LINE(' FS1 Blocks = '||l_fs1_blocks||'
Bytes = '||l_fs1_bytes);
DBMS_OUTPUT.PUT_LINE(' FS2 Blocks = '||l_fs2_blocks||'
Bytes = '||l_fs2_bytes);
SYSTOOLS
DBMS_OUTPUT.PUT_LINE(' FS3 Blocks = '||l_fs3_blocks||'
Bytes = '||l_fs3_bytes);
DBMS_OUTPUT.PUT_LINE(' FS4 Blocks = '||l_fs4_blocks||'
Bytes = '||l_fs4_bytes);
DBMS_OUTPUT.PUT_LINE('Full Blocks = '||l_full_blocks||'
Bytes = '||l_full_bytes);
DBMS_OUTPUT.PUT_LINE('====================================
=========');
DBMS_OUTPUT.PUT_LINE('Total Blocks =
'||to_char(l_fs1_blocks + l_fs2_blocks +
l_fs3_blocks + l_fs4_blocks + l_full_blocks)|| ' ||
Total Bytes = '|| to_char(l_fs1_bytes + l_fs2_bytes
+ l_fs3_bytes + l_fs4_bytes + l_full_bytes));
END;
• Query:
SYSTOOLS
SELECT id, full_name , resume -- CLOB
FROM customer_profiles
WHERE id IN (164, 150);
• Output in SQL*Plus:
ID FULL_NAME RESUME
---------- ----------------- ---------------------------
164 Charlotte Kazan Date of Birth: 8 Februa
ry 1951 Resigned = 5 June 2000
150 Harry Dean Fonda Date of Birth: 1 June 1
SYSTOOLS
956 Resigned = 30 September 2000
• Output in SQL Developer:
SYSTOOLS
SYSTOOLS
• DBMS_LOB.SUBSTR (lob, amount, start_pos)
• DBMS_LOB.INSTR (lob, pattern)
SELECT DBMS_LOB.SUBSTR (resume, 5, 18),
DBMS_LOB.INSTR (resume,' = ')
FROM customer_profiles
WHERE id IN (150, 164);
DBMS_LOB.SUBSTR(RESUME,5,18) SQL*Plus
-----------------------------------------------
-----------------------------------------------
DBMS_LOB.INSTR(RESUME,'=')
--------------------------
Febru
SYSTOOLS
40
June
36
SQL Developer
SYSTOOLS
Use DBMS_LOB.INSTR to search for information within the LOB. This function returns the
numerical position of the information.
SYSTOOLS
SET LINESIZE 50 SERVEROUTPUT ON FORMAT WORD_WRAP
DECLARE
text VARCHAR2(4001);
BEGIN
SELECT resume INTO text
FROM customer_profiles
WHERE id = 150;
DBMS_OUTPUT.PUT_LINE('text is: '|| text);
END;
/
SYSTOOLS
anonymous block completed
text is: Date of Birth: 1 June 1956 Resigned = 30
September 2000
SYSTOOLS
SYSTOOLS
• Delete a row containing LOBs:
DELETE
FROM customer_profiles
WHERE id = 164;
SYSTOOLS
7 - 43 Copyright © 2008, Oracle. All rights reserved.
Removing LOBs
A LOB instance can be deleted (destroyed) by using the appropriate SQL DML statements. The
SQL statement DELETE deletes a row and its associated internal LOB value. To preserve the
row and destroy only the reference to the LOB, you must update the row by replacing the LOB
column value with NULL or an empty string, or by using the EMPTY_B/CLOB() function.
SYSTOOLS
Note: Replacing a column value with NULL and using EMPTY_B/CLOB are not the same. Using
NULL sets the value to null; using EMPTY_B/CLOB ensures that nothing is in the column.
A LOB is destroyed when the row containing the LOB column is deleted, when the table is
dropped or truncated, or when all LOB data is updated.
You must explicitly remove the file associated with a BFILE by using the OS commands.
To erase part of an internal LOB, you can use DBMS_LOB.ERASE.
•
•
SYSTOOLS
Introduction to LOBs
Managing BFILEs by using the DBMS_LOB package
• Migrating LONG data types to LOBs
• Manipulating LOB data
• Using temporary LOBs
SYSTOOLS
7 - 44 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• Temporary LOBs:
– Provide an interface to support creation of LOBs that act like
local variables
– Can be BLOBs, CLOBs, or NCLOBs
– Are not associated with a specific table
– Are created by using the DBMS_LOB.CREATETEMPORARY
procedure
– Use DBMS_LOB routines
• The lifetime of a temporary LOB is a session.
SYSTOOLS
• Temporary LOBs are useful for transforming data in
permanent internal LOBs.
Temporary LOBs
Temporary LOBs provide an interface to support the creation and deletion of LOBs that act like
local variables. Temporary LOBs can be BLOBs, CLOBs, or NCLOBs.
The following are the features of temporary LOBs:
• Data is stored in your temporary tablespace, not in tables.
• Temporary LOBs are faster than persistent LOBs, because they do not generate redo or
SYSTOOLS
rollback information.
• Temporary LOBs lookup is localized to each user’s own session. Only the user who creates
a temporary LOB can access it, and all temporary LOBs are deleted at the end of the session
in which they were created.
• You can create a temporary LOB by using DBMS_LOB.CREATETEMPORARY.
Temporary LOBs are useful when you want to perform a transformational operation on a LOB
(for example, changing an image type from GIF to JPEG). A temporary LOB is empty when
created and does not support the EMPTY_B/CLOB functions.
Use the DBMS_LOB package to use and manipulate temporary LOBs.
SYSTOOLS
The PL/SQL procedure to create and test a temporary LOB:
SYSTOOLS
-- free the temporary LOB
DBMS_LOB.FREETEMPORARY (p_lob);
END;
/
SYSTOOLS
package as follows:
• The CREATETEMPORARY procedure is used to create the temporary LOB.
• The ISOPEN function is used to test whether a LOB is open: This function returns the value
1 if the LOB is open.
• The FREETEMPORARY procedure is used to free the temporary LOB. Memory increases
incrementally as the number of temporary LOBs grows, and you can reuse the temporary
LOB space in your session by explicitly freeing temporary LOBs.
SYSTOOLS
In this lesson, you should have learned how to:
• Identify four built-in types for large objects: BLOB, CLOB,
NCLOB, and BFILE
• Describe how LOBs replace LONG and LONG RAW
• Describe two storage options for LOBs:
– Oracle server (internal LOBs)
– External host files (external LOBs)
• Use the DBMS_LOB PL/SQL package to provide routines for
LOB management
SYSTOOLS
• Use temporary LOBs in a session
Summary
There are four LOB data types:
• A BLOB is a binary large object.
• A CLOB is a character large object.
• An NCLOB stores multiple-byte national character set data.
• A BFILE is a large object stored in a binary file outside the database.
SYSTOOLS
LOBs can be stored internally (in the database) or externally (in an OS file). You can manage
LOBs by using the DBMS_LOB package and its procedure.
Temporary LOBs provide an interface to support the creation and deletion of LOBs that act like
local variables.
SYSTOOLS
This practice covers the following topics:
• Creating object types by using the CLOB and BLOB data
types
• Creating a table with the LOB data types as columns
• Using the DBMS_LOB package to populate and interact with
the LOB data
SYSTOOLS
7 - 48 Copyright © 2008, Oracle. All rights reserved.
Practice 7: Overview
In this practice, you create a table with both BLOB and CLOB columns. Then, you use the
DBMS_LOB package to populate the table and manipulate the data.
Use the OE schema for this practice.
For detailed instructions about performing this practice, see Appendix A, “Practice Solutions.”
SYSTOOLS
SYSTOOLS
DBMS_LOB package to populate the table and manipulate the data.
Working with LOBs
1. Create a table called PERSONNEL by executing the
D:\Labs\labs\lab_07_01.sql script file. The table contains the following
attributes and data types:
Column Name Data Type Length
ID NUMBER 6
last_name VARCHAR2 35
review CLOB N/A
picture BLOB N/A
2. Insert two rows into the PERSONNEL table, one each for employee 2034 (whose last
name is Allen) and employee 2035 (whose last name is Bond). Use the empty function
SYSTOOLS
for the CLOB, and provide NULL as the value for the BLOB.
3. Examine and execute the D:\labs\labs\lab_07_03.sql script. The script creates
a table named REVIEW_TABLE. This table contains the annual review information for
each employee. The script also contains two statements to insert review details about two
employees.
4. Update the PERSONNEL table.
a. Populate the CLOB for the first row by using this subquery in an UPDATE statement:
SELECT ann_review
FROM review_table
WHERE employee_id = 2034;
b. Populate the CLOB for the second row by using PL/SQL and the DBMS_LOB package.
Use the following SELECT statement to provide a value for the LOB locator.
SELECT ann_review
FROM review_table
SYSTOOLS
WHERE employee_id = 2035;
5. Create a procedure that adds a locator to a binary file into the PICTURE column of the
PRODUCT_INFORMATION table. The binary file is a picture of the product. The image
files are named after the product IDs. You must load an image file locator into all rows in
the Printers category (CATEGORY_ID = 12) in the PRODUCT_INFORMATION table.
a. Create a DIRECTORY object called PRODUCT_PIC that references the location of
the binary. These files are available in the
D:\Labs\DATA_FILES\PRODUCT_PIC folder.
CREATE DIRECTORY product_pic AS
'D:\Labs\DATA_FILES\PRODUCT_PIC';
(Alternatively, use the D:\labs\labs\lab_07_05a.sql script.)
SYSTOOLS
exists, set the BFILE locator for the file in the PICTURE column; otherwise, display
a message that the file does not exist. Use the DBMS_OUTPUT package to report file
size information about each image associated with the PICTURE column.
(Alternatively, use the D:\labs\labs\lab_07_05_c.sql file.)
d. Invoke the procedure by passing the name of the PRODUCT_PIC directory object as a
string literal parameter value.
e. Check the LOB space usage of the PRODUCT_INFORMATION table. Use the
D:\labs\labs\lab_07_05_e.sql file to create the procedure and execute it.
SYSTOOLS
SYSTOOLS
SYSTOOLS
Administering SecureFile LOBs
SYSTOOLS
Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Objectives
SYSTOOLS
After completing this lesson, you should be able to:
• Describe SecureFile LOB features
• Enable SecureFile LOB deduplication, compression, and
encryption
• Migrate BasicFile LOBs to the SecureFile LOB format
• Analyze the performance of LOBs
SYSTOOLS
8-2 Copyright © 2008, Oracle. All rights reserved.
Objectives
In this lesson, you learn to migrate the pre-Oracle Database 11g LOB storage format (called
BasicFile LOB format) to the SecureFile LOB format. You also compare the performance of
LOBs stored in the BasicFile format with the SecureFile format. Finally, you learn how to enable
SecureFile LOB deduplication (storage sharing), compression, and encryption.
SYSTOOLS
SYSTOOLS
• SecureFile LOB features
• Deduplication, compression, and encryption
• Migration of BasicFile LOBs to the SecureFile LOB format
• Performance of LOBs
SYSTOOLS
8-3 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
Oracle Database 11g offers a reengineered large object (LOB)
data type that:
• Improves performance
• Eases manageability
• Simplifies application development
• Offers advanced, next-generation functionality such as
intelligent compression and transparent encryption
SYSTOOLS
8-4 Copyright © 2008, Oracle. All rights reserved.
SecureFile LOBs
With SecureFile LOBs, the LOB data type is completely reengineered with dramatically
improved performance, manageability, and ease of application development. This
implementation, available with Oracle Database 11g, also offers advanced, next-generation
functionality such as intelligent compression and transparent encryption. This feature
SYSTOOLS
significantly strengthens the native content management capabilities of Oracle Database.
SecureFile LOBs were introduced to supplement the implementation of original BasicFile LOBs
that are identified by the BASICFILE SQL parameter.
SYSTOOLS
Oracle Database 11g implements a new storage paradigm for
LOB storage:
• If the SECUREFILE storage keyword appears in the CREATE
TABLE statement, the new storage is used.
• If the BASICFILE storage keyword appears in the CREATE
TABLE statement, the old storage paradigm is used.
• By default, the storage is BASICFILE, unless you modify the
setting for the DB_SECUREFILE parameter in the init.ora
file.
SYSTOOLS
8-5 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
You can modify the init.ora file and change the default behavior for the storage of LOBs by
setting the DB_SECUREFILE initialization parameter. The values allowed are:
• ALWAYS: Attempts to create all LOB files as SECUREFILES but creates any LOBs not in
ASSM tablespaces as BASICFILE LOBs
• FORCE: All LOBs created in the system are created as SECUREFILE LOBs.
• PERMITTED: The default; allows SECUREFILES to be created when specified with the
SECUREFILE keyword in the CREATE TABLE statement
• NEVER: Creates LOBs that are specified as SECUREFILE LOBs as BASICFILE LOBs
• IGNORE: Ignores the SECUREFILE keyword and all SECUREFILE options
SYSTOOLS
• Create a tablespace for the LOB data:
-- have your dba do this:
CREATE TABLESPACE sf_tbs1
DATAFILE 'sf_tbs1.dbf' SIZE 1500M REUSE
1
AUTOEXTEND ON NEXT 200M
MAXSIZE 3000M
SEGMENT SPACE MANAGEMENT AUTO;
• Create a table to hold the LOB data:
CONNECT oe
CREATE TABLE customer_profiles_sf
(id NUMBER,
SYSTOOLS
first_name VARCHAR2 (40),
last_name VARCHAR2 (80), 2
profile_info BLOB)
LOB(profile_info) STORE AS SECUREFILE
(TABLESPACE sf_tbs1);
SYSTOOLS
In the example shown in the slide:
1. The sf_tbs1 tablespace is defined. This tablespace stores the LOB data in the SecureFile
format. When you define a column to hold SecureFile data, you must have Automatic
Segment Space Management (ASSM) enabled for the tablespace in order to support
SecureFiles.
2. The CUSTOMER_PROFILES_SF table is created. The PROFILE_INFO column holds
the LOB data in the SecureFile format, because the storage clause identifies the format.
SYSTOOLS
Writing data to a SECUREFILE LOB works in the same way as
writing data to a BASICFILE LOB.
• Create the DIRECTORY object in the database that points to
the location where the external documents are stored.
• Create a procedure to read the LOB data into the LOB
column.
• Create a procedure to insert LOB data into the table (which
references the procedure that reads the LOB data).
• Execute the insert procedure and specify the file that you
SYSTOOLS
want to insert.
SYSTOOLS
SYSTOOLS
Reading data from a SECUREFILE LOB works in the same way
as reading data from a BASICFILE LOB.
• Create a procedure to specify the LOB data that you want to
read from the table.
• Execute the procedure to read the table.
SYSTOOLS
8-8 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• SecureFile LOB features
• Deduplication, compression, and encryption
• Migration of BasicFile LOBs to the SecureFile LOB format
• Performance of LOBs
SYSTOOLS
8-9 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
To enable deduplication and compression, use the ALTER
TABLE statement with the DEDUPLICATE and COMPRESS
options.
• By enabling deduplication with SecureFiles, duplicate LOB
data is automatically detected and space is conserved by
storing only one copy.
• Enabling compression turns on LOB compression.
ALTER TABLE tblname
MODIFY LOB lobcolname
SYSTOOLS
(DEDUPLICATE option
COMPRESS option)
SYSTOOLS
KEEP_DUPLICATES. Using a secure hash index to detect duplication, the database combines
LOBs with identical content into a single copy, thereby reducing storage and simplifying storage
management. You can also use DBMS_LOB.SETOPTIONS to enable or disable deduplication
on individual LOBs.
The options for the COMPRESS clause are:
• COMPRESS HIGH: Provides the best compression but incurs the most work
• COMPRESS MEDIUM: Is the default value
• NOCOMPRESS: Disables compression
SYSTOOLS
8 - 11 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
column in the CUSTOMER_PROFILES_SF table.
In the third step, you examine the space being used after deduplication and compression are
enabled.
In the fourth step, you reclaim the space and examine the results.
IS
SYSTOOLS
CREATE OR REPLACE PROCEDURE check_sf_space
l_fs1_bytes NUMBER;
l_fs2_bytes NUMBER;
...
BEGIN
DBMS_SPACE.SPACE_USAGE(
segment_owner => 'OE',
segment_name => 'CUSTOMER_PROFILES_SF',
segment_type => 'TABLE',
fs1_bytes => l_fs1_bytes,
fs1_blocks => l_fs1_blocks,
fs2_bytes => l_fs2_bytes,
fs2_blocks => l_fs2_blocks, …
);
DBMS_OUTPUT.ENABLE;
DBMS_OUTPUT.PUT_LINE(' FS1 Blocks = '||l_fs1_blocks||'
SYSTOOLS
Bytes = '||l_fs1_bytes);
DBMS_OUTPUT.PUT_LINE(' FS2 Blocks = '||l_fs2_blocks||'
Bytes = '||l_fs2_bytes); …
DBMS_OUTPUT.PUT_LINE('=======================================');
DBMS_OUTPUT.PUT_LINE('Total Blocks =
'||to_char(l_fs1_blocks + l_fs2_blocks));
...
END;
SYSTOOLS
Note: The full code for the CHECK_SF_SPACE procedure is shown on the next page.
SYSTOOLS
IS
l_fs1_bytes NUMBER; l_fs2_bytes NUMBER;
l_fs3_bytes NUMBER; l_fs4_bytes NUMBER;
l_fs1_blocks NUMBER; l_fs2_blocks NUMBER;
l_fs3_blocks NUMBER; l_fs4_blocks NUMBER;
l_full_bytes NUMBER; l_full_blocks NUMBER;
l_unformatted_bytes NUMBER;
l_unformatted_blocks NUMBER;
BEGIN
DBMS_SPACE.SPACE_USAGE(
segment_owner => 'OE',
segment_name => 'CUSTOMER_PROFILES_SF',
segment_type => 'TABLE',
fs1_bytes => l_fs1_bytes,
fs1_blocks => l_fs1_blocks,
fs2_bytes => l_fs2_bytes,
SYSTOOLS
fs2_blocks => l_fs2_blocks,
fs3_bytes => l_fs3_bytes,
fs3_blocks => l_fs3_blocks,
fs4_bytes => l_fs4_bytes,
fs4_blocks => l_fs4_blocks,
full_bytes => l_full_bytes,
full_blocks => l_full_blocks,
unformatted_blocks => l_unformatted_blocks,
unformatted_bytes => l_unformatted_bytes
);
DBMS_OUTPUT.ENABLE;
DBMS_OUTPUT.PUT_LINE(' FS1 Blocks = '||l_fs1_blocks||'
Bytes = '||l_fs1_bytes);
DBMS_OUTPUT.PUT_LINE(' FS2 Blocks = '||l_fs2_blocks||'
Bytes = '||l_fs2_bytes);
DBMS_OUTPUT.PUT_LINE(' FS3 Blocks = '||l_fs3_blocks||'
SYSTOOLS
Bytes = '||l_fs3_bytes);
DBMS_OUTPUT.PUT_LINE(' FS4 Blocks = '||l_fs4_blocks||'
Bytes = '||l_fs4_bytes);
DBMS_OUTPUT.PUT_LINE('Full Blocks = '||l_full_blocks||'
Bytes = '||l_full_bytes);
DBMS_OUTPUT.PUT_LINE('===============================
==============');
DBMS_OUTPUT.PUT_LINE('Total Blocks =
'||to_char(l_fs1_blocks + l_fs2_blocks +
l_fs3_blocks + l_fs4_blocks + l_full_blocks)|| ' ||
Total Bytes = '|| to_char(l_fs1_bytes + l_fs2_bytes
+ l_fs3_bytes + l_fs4_bytes + l_full_bytes));
END check_sf_space;
SYSTOOLS
Execution Results:
EXECUTE check_sf_space
SYSTOOLS
PL/SQL procedure successfully completed.
SYSTOOLS
Table altered.
SYSTOOLS
8 - 15 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
PL/SQL procedure successfully completed.
SYSTOOLS
SYSTOOLS
8 - 17 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
(HWM)—but the HWM itself is not disturbed.
3. The third statement (ALTER TABLE resumes SHRINK SPACE) returns unused blocks to
the database and resets the HWM, moving it to a lower position. Lowering the HWM
should result in better full-table scan reads.
Rechecking LOB Space Usage
EXECUTE check_sf_space
FS1 Blocks = 0 Bytes = 0
FS2 Blocks = 1 Bytes = 8192
FS3 Blocks = 0 Bytes = 0
FS4 Blocks = 0 Bytes = 0
Full Blocks = 0 Bytes = 0
================================
Total Blocks = 1 ||
Total Bytes = 8192
SYSTOOLS
The encryption option enables you to turn the LOB encryption
on or off, and optionally select an encryption algorithm.
• Encryption is performed at the block level.
• You can specify the encryption algorithm:
– 3DES168
– AES128
– AES192 (default)
– AES256
• The column encryption key is derived by using Transparent
Data Encryption.
SYSTOOLS
• All LOBs in the LOB column are encrypted.
• DECRYPT keeps the LOBs in cleartext.
• LOBs can be encrypted on a per-column or per-partition
basis.
8 - 18 Copyright © 2008, Oracle. All rights reserved.
Using Encryption
You can create a table or alter a table with encryption enabled or disabled on a LOB column. The
current Transparent Data Encryption (TDE) syntax is used for extending encryption to LOB data
types.
SYSTOOLS
SYSTOOLS
1. Create a directory to store the Transparent Data Encryption
(TDE) wallet.
mkdir d:\etc\oracle\wallets
2. Edit the <ORACLE_HOME>\network\admin\sqlnet.ora file
to indicate the location of the TDE wallet.
ENCRYPTION_WALLET_LOCATION=(SOURCE=(METHOD=FILE)
(METHOD_DATA= (DIRECTORY=d:\etc\oracle\wallets)))
3. Stop and start the listener for the change to take effect.
LSNRCTL RELOAD
SYSTOOLS
4. To open the wallet, log in to SQL*Plus as SYSDBA and
execute the following command:
ALTER system SET KEY IDENTIFIED BY "welcome1";
SYSTOOLS
columns, regardless of the number of encrypted columns in a given table. Each table’s column
encryption key is, in turn, encrypted with the database server’s master key. No keys are stored in
the database. Instead, they are stored in an Oracle wallet, which is part of the external security
module.
To enable TDE, perform the following:
1. Create a directory to store the TDE wallet.
2. Modify the sqlnet.ora file to identify the location of the TDE wallet, as shown in the
slide. Make sure that the wallet location is set to a location outside the Oracle installation to
avoid ending up on a backup tape together with encrypted data.
3. Stop and start the listener to have the change take effect: LSNRCTL RELOAD
4. Open the wallet. Log in to SQL*Plus as the SYS user and execute the following command:
ALTER system SET KEY IDENTIFIED BY “welcome”;
SYSTOOLS
• Enable encryption:
ALTER TABLE customer_profiles_sf
MODIFY (profile_info ENCRYPT USING 'AES192');
Table altered.
• Verify that the LOB is encrypted:
SELECT *
FROM user_encrypted_columns;
SYSTOOLS
----------------- ----------------- ---------------- ---
CUSTOMER_PROFILES PROFILE_INFO AES 192 bits key YES
SYSTOOLS
SYSTOOLS
• SecureFile LOB features
• Deduplication, compression, and encryption
• Migration of BasicFile LOBs to the SecureFile LOB format
• Performance of LOBs
SYSTOOLS
8 - 21 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
Check the LOB segment subtype name for the BasicFile format:
col segment_name format a30
col segment_type format a13
SYSTOOLS
SYS_LOB0000080068C00004$$ LOBSEGMENT ASSM
SYSTOOLS
SYSTOOLS
• The migration from BasicFile to SecureFiles LOB storage
format is performed online.
• This means that the CUSTOMER_PROFILES table continues
to be accessible during the migration.
• This type of operation is called online redefinition.
connect oe
CREATE TABLE customer_profiles_interim
(id NUMBER,
full_name VARCHAR2 (45),
resume CLOB,
SYSTOOLS
picture BLOB)
LOB(picture) STORE AS SECUREFILE
(TABLESPACE lob_tbs1);
SYSTOOLS
SYSTOOLS
Call the DBMS_REDEFINITION package to perform the online
redefinition operation:
connect /as sysdba
DECLARE
error_count PLS_INTEGER := 0;
BEGIN
DBMS_REDEFINITION.START_REDEF_TABLE
('OE', 'customer_profiles', 'customer_profiles_interim',
'id id, full_name full_name,
resume resume, picture picture',
OPTIONS_FLAG => DBMS_REDEFINITION.CONS_USE_ROWID);
DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS
SYSTOOLS
('OE', 'customer_profiles', 'customer_profiles_interim',
1, true,true,true,false, error_count);
DBMS_OUTPUT.PUT_LINE('Errors := ' || TO_CHAR(error_count));
DBMS_REDEFINITION.FINISH_REDEF_TABLE
('OE', 'customer_profiles', 'customer_profiles_interim');
END;
SYSTOOLS
Now, check the segment type of the migrated LOB. Note that the segment subtype for SecureFile
LOB storage is SECUREFILE; for BasicFile format, it is ASSM.
SELECT segment_name, segment_type, segment_subtype
FROM dba_segments
WHERE tablespace_name = 'LOB_TBS1'
AND segment_type = 'LOBSEGMENT'
/
SYSTOOLS
• SecureFile LOB features
• Deduplication, compression, and encryption
• Migration of BasicFile LOBs to the SecureFile LOB format
• Performance of LOBs
SYSTOOLS
8 - 25 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
Compare the performance on loading and reading LOB columns
in the SecureFile and BasicFile formats:
SYSTOOLS
8 - 26 Copyright © 2008, Oracle. All rights reserved.
Performance
In the examples shown in this lesson and the previous lesson, the performance on loading and
reading data in the LOB column of the SecureFile format LOB is faster than that of the BasicFile
format LOB.
SYSTOOLS
SYSTOOLS
In this lesson, you should have learned how to:
• Describe SecureFile LOB features
• Enable SecureFile LOB deduplication, compression, and
encryption
• Migrate BasicFile LOBs to the SecureFile LOB format
• Analyze the performance of LOBs
SYSTOOLS
8 - 27 Copyright © 2008, Oracle. All rights reserved.
Summary
In this lesson, you learned about the new SecureFile format for LOBs. You learned that the
SecureFile format offers features such as deduplication, compression, and encryption. You
learned how to migrate the older version BasicFile format to the SecureFile format, and also
learned that the performance of SecureFile format LOBs is faster than the BasicFile format
SYSTOOLS
LOBs.
SYSTOOLS
Using SecureFile Format LOBs
This practice covers the following topics:
• Setting up the environment for LOBs
• Migrating BasicFile LOBs to SecureFile LOBs
• Enabling deduplication and compression
SYSTOOLS
8 - 28 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
Working with SecureFile LOBs
1. In this practice, you migrate a BasicFile format LOB to a SecureFile format LOB. You need
to set up several supporting structures:
a. As the OE user, drop your existing PRODUCT_DESCRIPTIONS table and create a
new one:
DROP TABLE product_descriptions;
b. As the SYS user, create a new tablespace to store the LOB information.
CREATE TABLESPACE lob_tbs2
DATAFILE 'lob_tbs2.dbf' SIZE 1500M REUSE
AUTOEXTEND ON NEXT 200M
MAXSIZE 3000M
SYSTOOLS
SEGMENT SPACE MANAGEMENT AUTO;
c. Create a directory object that identifies the location of your LOBs. In the Oracle
classroom, the location is in the Oracle D:\labs\DATA_FILES\PRODUCT_PIC
folder. Then, grant read privileges on the directory to the OE user.
CREATE OR REPLACE DIRECTORY product_files
AS 'd:\Labs\DATA_FILES\PRODUCT_PIC ';
d. As the OE user, alter the table and add a BLOB column of the BASICFILE storage
type.
ALTER TABLE product_descriptions ADD
(detailed_product_info BLOB )
LOB (detailed_product_info) STORE AS BASICFILE
(tablespace lob_tbs2);
SYSTOOLS
e. Create the procedure to load the LOB data into the column (You can run the
D:\Labs\labs\lab_08_01_e.sql script.):
CREATE OR REPLACE PROCEDURE loadLOBFromBFILE_proc (
p_dest_loc IN OUT BLOB, p_file_name IN VARCHAR2)
IS
v_src_loc BFILE := BFILENAME('PRODUCT_FILES', p_file_name);
v_amount INTEGER := 4000;
BEGIN
DBMS_LOB.OPEN(v_src_loc, DBMS_LOB.LOB_READONLY);
v_amount := DBMS_LOB.GETLENGTH(v_src_loc);
DBMS_LOB.LOADFROMFILE(p_dest_loc, v_src_loc, v_amount);
DBMS_LOB.CLOSE(v_src_loc);
END loadLOBFromBFILE_proc;
/
SYSTOOLS
CREATE OR REPLACE PROCEDURE write_lob (p_file IN
VARCHAR2)
IS
i NUMBER; v_id NUMBER; v_b BLOB;
BEGIN
DBMS_OUTPUT.ENABLE;
DBMS_OUTPUT.PUT_LINE('Begin inserting rows...');
FOR i IN 1 .. 5 LOOP
v_id:=SUBSTR(p_file, 1, 4);
INSERT INTO product_descriptions
VALUES (v_id, EMPTY_BLOB())
RETURNING detailed_product_info INTO v_b;
loadLOBFromBFILE_proc(v_b,p_file);
DBMS_OUTPUT.PUT_LINE('Row '|| i ||' inserted.');
END LOOP;
SYSTOOLS
COMMIT;
END write_lob;
/
g. As the OE user, execute the procedures to load the data. If you are using SQL*Plus,
you can set the timing on to observe the time. (You can run the
D:\Labs\lab\lab_08_01_g.sql script.)
Note: If you are using SQL Developer, issue only the EXECUTE statements listed as
follows. In SQL Developer, some of the SQL*Plus commands are ignored. It is
recommended that you use SQL*Plus for this exercise.
set serveroutput on
set verify on
set term on
set lines 200
SYSTOOLS
execute write_lob('1726_LCD.doc');
execute write_lob('1734_RS232.doc');
execute write_lob('1739_SDRAM.doc');
timing stop
h. As the SYSTEM user, check the segment type in the data dictionary.
SELECT segment_name, segment_type, segment_subtype
FROM dba_segments
WHERE tablespace_name = 'LOB_TBS2'
AND segment_type = 'LOBSEGMENT';
SYSTOOLS
(product_id NUMBER,
detailed_product_info BLOB)
LOB(detailed_product_info) STORE AS SECUREFILE
(TABLESPACE lob_tbs2);
j. Connect as the SYSTEM user and run the redefinition script. (You can run the
D:\Labs\lab\lab_08_01_j.sql script.)
DECLARE
error_count PLS_INTEGER := 0;
BEGIN
DBMS_REDEFINITION.START_REDEF_TABLE
('OE', 'product_descriptions',
'product_descriptions_interim',
'product_id product_id, detailed_product_info
detailed_product_info',
SYSTOOLS
OPTIONS_FLAG => DBMS_REDEFINITION.CONS_USE_ROWID);
DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS
('OE', 'product_descriptions',
'product_descriptions_interim',
1, true,true,true,false, error_count);
DBMS_OUTPUT.PUT_LINE('Errors := ' ||
TO_CHAR(error_count));
DBMS_REDEFINITION.FINISH_REDEF_TABLE
('OE', 'product_descriptions',
'product_descriptions_interim');
END;
/
SYSTOOLS
l. As the SYSTEM user, check the segment type in the data dictionary to make sure it
is now set to SECUREFILE.
SELECT segment_name, segment_type, segment_subtype
FROM dba_segments
WHERE tablespace_name = 'LOB_TBS2'
AND segment_type = 'LOBSEGMENT';
SYSTOOLS
CREATE OR REPLACE PROCEDURE check_space
IS
l_fs1_bytes NUMBER;
l_fs2_bytes NUMBER;
l_fs3_bytes NUMBER;
l_fs4_bytes NUMBER;
l_fs1_blocks NUMBER;
l_fs2_blocks NUMBER;
l_fs3_blocks NUMBER;
l_fs4_blocks NUMBER;
l_full_bytes NUMBER;
l_full_blocks NUMBER;
l_unformatted_bytes NUMBER;
l_unformatted_blocks NUMBER;
BEGIN
DBMS_SPACE.SPACE_USAGE(
segment_owner => 'OE',
SYSTOOLS
segment_name => 'PRODUCT_DESCRIPTIONS',
segment_type => 'TABLE',
fs1_bytes => l_fs1_bytes,
fs1_blocks => l_fs1_blocks,
fs2_bytes => l_fs2_bytes,
fs2_blocks => l_fs2_blocks,
fs3_bytes => l_fs3_bytes,
fs3_blocks => l_fs3_blocks,
fs4_bytes => l_fs4_bytes,
fs4_blocks => l_fs4_blocks,
full_bytes => l_full_bytes,
full_blocks => l_full_blocks,
unformatted_blocks => l_unformatted_blocks,
unformatted_bytes => l_unformatted_bytes
);
DBMS_OUTPUT.ENABLE;
DBMS_OUTPUT.PUT_LINE(' FS1 Blocks = '||l_fs1_blocks||'
SYSTOOLS
Bytes = '||l_fs1_bytes);
DBMS_OUTPUT.PUT_LINE(' FS2 Blocks = '||l_fs2_blocks||'
Bytes = '||l_fs2_bytes);
DBMS_OUTPUT.PUT_LINE(' FS3 Blocks = '||l_fs3_blocks||'
Bytes = '||l_fs3_bytes);
DBMS_OUTPUT.PUT_LINE(' FS4 Blocks = '||l_fs4_blocks||'
Bytes = '||l_fs4_bytes);
DBMS_OUTPUT.PUT_LINE('Full Blocks = '||l_full_blocks||'
Bytes = '||l_full_bytes);
DBMS_OUTPUT.PUT_LINE('====================================
=========');
SYSTOOLS
l_fs3_blocks + l_fs4_blocks + l_full_blocks)|| ' ||
Total Bytes = '|| to_char(l_fs1_bytes + l_fs2_bytes
+ l_fs3_bytes + l_fs4_bytes + l_full_bytes));
END;
/
set serveroutput on
execute check_space;
SYSTOOLS
SYSTOOLS
SYSTOOLS
SYSTOOLS
SYSTOOLS
Performance and Tuning
SYSTOOLS
Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Objectives
SYSTOOLS
After completing this lesson, you should be able to do the
following:
• Understand and influence the compiler
• Tune PL/SQL code
• Enable intraunit inlining
SYSTOOLS
9-2 Copyright © 2008, Oracle. All rights reserved.
Objectives
In this lesson, the performance and tuning topics are divided into three main groups:
• Native and interpreted compilation
• Tuning PL/SQL code
• Intraunit inlining
SYSTOOLS
In the compilation section, you learn about native and interpreted compilation.
In the “Tuning PL/SQL Code” section, you learn why it is important to write smaller, executable
sections of code, when to use SQL or PL/SQL, how bulk binds can improve performance, how
to use the FORALL syntax, how to rephrase conditional statements, about data types and
constraint issues.
With inlining, the compiler reviews code to see whether it can be inlined rather than referenced.
You can influence the inlining process.
SYSTOOLS
• Using native and interpreted compilation methods
• Tuning PL/SQL code
• Enabling intraunit inlining
SYSTOOLS
9-3 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
Two compilation methods:
• Interpreted compilation
– Default compilation method
– Interpreted at run time
• Native compilation
– Compiles into native code
– Stored in the SYSTEM tablespace
SYSTOOLS
9-4 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
interpreted at run time. You can use PL/SQL debugging tools on program units compiled for
interpreted mode.
With PL/SQL native compilation, the PL/SQL statements in a PL/SQL program unit are
compiled into native code and stored in the SYSTEM tablespace. Because the native code does
not have to be interpreted at run time, it runs faster.
Native compilation applies only to PL/SQL statements. If your PL/SQL program contains only
calls to SQL statements, it may not run faster when natively compiled, but it will run at least as
fast as the corresponding interpreted code. The compiled code and the interpreted code make the
same library calls, so their action is the same.
The first time a natively compiled PL/SQL program unit is executed, it is fetched from the
SYSTEM tablespace into the shared memory. Regardless of how many sessions call the program
unit, the shared memory has only one copy of it. If a program unit is not being used, the shared
memory it is using might be freed, to reduce the memory load.
SYSTOOLS
• Use the interpreted mode when (typically during
development):
– You are using a debugging tool, such as SQL Developer
– You need the code compiled quickly
• Use the native mode when (typically post development):
– Your code is heavily PL/SQL based
– You are looking for increased performance in production
Native
SYSTOOLS Interpreted
SYSTOOLS
advantages:
• You can use PL/SQL debugging tools on program units compiled for interpreted mode (but
not for those compiled for native mode).
• Compiling for interpreted mode is faster than compiling for native mode.
After completing the debugging phase of development, consider the following in determining
whether to compile a PL/SQL program unit for native mode:
• The native mode provides the greatest performance gains for computation-intensive
procedural operations. Examples are data warehouse applications and applications with
extensive server-side transformations of data for display.
• The native mode provides the least performance gains for PL/SQL subprograms that spend
most of their time executing SQL.
• When many program units (typically over 15,000) are compiled for native execution, and
are simultaneously active, the large amount of shared memory required might affect system
performance.
SYSTOOLS
• PLSQL_CODE_TYPE: Specifies the compilation mode for the
PL/SQL library units
PLSQL_CODE_TYPE = { INTERPRETED | NATIVE }
SYSTOOLS
PLSQL_CODE_TYPE = NATIVE
PLSQL_OPTIMIZE_LEVEL = 2
SYSTOOLS
• PL/SQL library units are compiled to PL/SQL bytecode format.
• These modules are executed by the PL/SQL interpreter engine.
If you choose NATIVE:
• PL/SQL library units (with the possible exception of top-level anonymous PL/SQL blocks)
are compiled to native (machine) code.
• Such modules are executed natively without incurring interpreter overhead.
When the value of this parameter is changed, it has no effect on the PL/SQL library units that
have already been compiled. The value of this parameter is stored persistently with each library
unit. If a PL/SQL library unit is compiled natively, all subsequent automatic recompilations of
that library unit use the native compilation. In Oracle Database 11g, native compilation is easier
and more integrated, with fewer initialization parameters to set.
SYSTOOLS
This parameter specifies the optimization level that is used to compile the PL/SQL library units.
The higher the setting of this parameter, the more effort the compiler makes to optimize the
PL/SQL library units. The available values are (0, 1, and 2 were available starting with Oracle
10g, release 2):
0: Maintains the evaluation order and hence the pattern of side effects, exceptions, and package
initializations of Oracle9i and earlier releases. Also removes the new semantic identity of
BINARY_INTEGER and PLS_INTEGER, and restores the earlier rules for the evaluation of
integer expressions. Although the code runs somewhat faster than it did in Oracle9i, the use of
level 0 forfeits most of the performance gains of PL/SQL starting with Oracle Database 10g.
1: Applies a wide range of optimizations to PL/SQL programs, including the elimination of
unnecessary computations and exceptions, but generally does not move source code out of its
original source order.
2: Applies a wide range of modern optimization techniques beyond those of level 1, including
changes that may move source code relatively far from its original location.
SYSTOOLS
3: This value is available in Oracle Database 11g. It applies a wide range of optimization
techniques beyond those of level 2, automatically including techniques not specifically
requested. This enables procedure inlining, which is an optimization process that replaces
procedure calls with a copy of the body of the procedure to be called. The copied procedure
almost always runs faster than the original call. To allow subprogram inlining, either accept the
default value of the PLSQL_OPTIMIZE_LEVEL initialization parameter (which is 2) or set it
to 3. With PLSQL_OPTIMIZE_LEVEL = 2, you must specify each subprogram to be inlined.
With PLSQL_OPTIMIZE_LEVEL = 3, the PL/SQL compiler seeks opportunities to inline
subprograms beyond those that you specify.
Generally, setting this parameter to 2 pays off in terms of better execution performance. If,
however, the compiler runs slowly on a particular source module or if optimization does not
make sense for some reason (for example, during rapid turnaround development), setting this
parameter to 1 results in almost as good a compilation with less use of compile-time resources.
The value of this parameter is stored persistently with the library unit.
SYSTOOLS
SYSTOOLS
Use the USER|ALL|DBA_PLSQL_OBJECT_SETTINGS data
dictionary views to display the settings for a PL/SQL object:
DESCRIBE ALL_PLSQL_OBJECT_SETTINGS
SYSTOOLS
PLSQL_CODE_TYPE VARCHAR2(4000)
PLSQL_DEBUG VARCHAR2(4000)
PLSQL_WARNINGS VARCHAR2(4000)
NLS_LENGTH_SEMANTICS VARCHAR2(4000)
PLSQL_CCFLAGS VARCHAR2(4000)
PLSCOPE_SETTINGS VARCHAR2(4000)
SYSTOOLS
Type: The available choices are PROCEDURE, FUNCTION, PACKAGE, PACKAGE BODY,
TRIGGER, TYPE, or TYPE BODY.
PLSQL_OPTIMIZE_LEVEL: The optimization level that was used to compile the object
PLSQL_CODE_TYPE: The compilation mode for the object
PLSQL_DEBUG: Specifies whether or not the object was compiled for debugging
PLSQL_WARNINGS: The compiler warning settings used to compile the object
NLS_LENGTH_SEMANTICS: The national language support (NLS) length semantics used to
compile the object
PLSQL_CCFLAGS: The conditional compilation flag used to compile the object
PLSCOPE_SETTINGS: Controls the compile time collection, cross reference, and storage of
PL/SQL source code identifier data (new in Oracle Database 11g)
SYSTOOLS
SELECT name, plsql_code_type, plsql_optimize_level
FROM user_plsql_object_settings;
SYSTOOLS
CATALOG_TYP INTERPRETED 2
CATEGORY_TYP INTERPRETED 2
CATEGORY_TYP INTERPRETED 2
COMPOSITE_CATEGORY_TYP INTERPRETED 2
...
SYSTOOLS
SYSTOOLS
• This requires DBA privileges.
• The PLSQL_CODE_TYPE compilation parameter must be
set to NATIVE.
• The benefits apply to all the built-in PL/SQL packages that
are used for many database operations.
ALTER SYSTEM SET PLSQL_CODE_TYPE = NATIVE;
SYSTOOLS
9 - 10 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
SELECT name, plsql_code_type, plsql_optimize_level
1
FROM user_plsql_object_settings
WHERE name = 'ADD_ORDER_ITEMS';
SYSTOOLS
FROM user_plsql_object_settings
WHERE name = 'ADD_ORDER_ITEMS';
SYSTOOLS
1. The compilation type is checked on the ADD_ORDER_ITEMS program unit.
2. The compilation method is set to NATIVE at the session level.
3. The ADD_ORDER_ITEMS program unit is recompiled.
4. The compilation type is checked again on the ADD_ORDER_ITEMS program unit to verify
that it changed.
If you want to compile an entire database for native or interpreted compilation, scripts are
provided to help you do so.
• You require DBA privileges.
• Set PLSQL_CODE_TYPE at the system level.
• Run the dbmsupgnv.sql-supplied script that is found in the
\Oraclehome\product\11.1.0\db_1\RDBMS\ADMIN folder.
For detailed information, see the Oracle® Database PL/SQL Language Reference 11g reference
manual.
SYSTOOLS
• Using native and interpreted compilation methods
• Tuning PL/SQL code
• Enabling intraunit inlining
SYSTOOLS
9 - 12 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
You can tune your PL/SQL code by:
• Identifying the data type and constraint issues
– Data type conversion
– The NOT NULL constraint
– PLS_INTEGER
– SIMPLE_INTEGER
• Writing smaller executable sections of code
• Comparing SQL with PL/SQL
• Understanding how bulk binds can improve performance
SYSTOOLS
• Using the FORALL support with bulk binding
• Handling and saving exceptions with the SAVE
EXCEPTIONS syntax
• Rephrasing conditional statements
SYSTOOLS
SYSTOOLS
• PL/SQL performs implicit conversions between structurally
different data types.
• Example: When assigning a PLS_INTEGER variable to a
NUMBER variable
DECLARE
n NUMBER;
BEGIN
n := n + 15; -- converted
n := n + 15.0; -- not converted
SYSTOOLS
...
END;
numbers strings
dates
SYSTOOLS
• You have no control over the implicit conversion.
In the slide example, assigning a PLS_INTEGER variable to a NUMBER variable or vice versa
results in a conversion, because their representations are different. Such implicit conversions can
happen during parameter passing as well. The integer literal 15 is represented internally as a
signed 4-byte quantity, so PL/SQL must convert it to an Oracle number before the addition.
However, the floating-point literal 15.0 is represented as a 22-byte Oracle number, so no
conversion is necessary.
To avoid implicit data type conversion, you can use the built-in functions:
• TO_DATE
• TO_NUMBER
• TO_CHAR
• CAST
SYSTOOLS
PROCEDURE calc_m IS PROCEDURE calc_m IS
m NUMBER NOT NULL:=0; m NUMBER; --no
a NUMBER; --constraint
b NUMBER; a NUMBER;
BEGIN b NUMBER;
... BEGIN
m := a + b; ...
... m := a + b;
END; IF m IS NULL THEN
SYSTOOLS
-- raise error
END IF;
END;
SYSTOOLS
assigned to m. Otherwise, an exception is raised. However, if m were not constrained, the value
would be assigned to m directly.
A more efficient way to write the same example is shown on the right in the slide.
Note that the subtypes NATURALN and POSTIVEN are defined as the NOT NULL subtypes of
NATURAL and POSITIVE. Using them incurs the same performance cost as seen above.
Using the NOT NULL Constraint Not Using the Constraint
Slower Faster
No extra coding is needed. Requires extra coding that is error prone
When an error is implicitly raised, the When an error is explicitly raised, the
value of m is preserved. old value of m is lost.
SYSTOOLS
Use PLS_INTEGER when dealing with integer data:
• It is an efficient data type for integer variables.
• It requires less storage than INTEGER or NUMBER.
• Its operations use machine arithmetic, which is faster than
library arithmetic.
SYSTOOLS
9 - 16 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
BINARY_INTEGER, INTEGER, or NUMBER operations, which use library arithmetic.
Furthermore, INTEGER, NATURAL, NATURALN, POSITIVE, POSITIVEN, and SIGNTYPE
are constrained subtypes. Their variables require precision checking at run time that can affect
the performance.
The BINARY_FLOAT and BINARY_DOUBLE data types are also faster than the NUMBER data
type.
–
SYSTOOLS
• Definition:
Is a predefined subtype
– Has the range –2147483648 .. 2147483648
– Does not include a null value
– Is allowed anywhere in PL/SQL where the PLS_INTEGER
data type is allowed
• Benefits:
– Eliminates the overhead of overflow
checking
SYSTOOLS
– Is estimated to be 2–10 times faster
when compared with the PLS_INTEGER
type with native PL/SQL compilation
SYSTOOLS
smallest value by one silently produces the largest value. These “wrap around” semantics
conform to the Institute of Electrical and Electronics Engineers (IEEE) standard for 32-bit
integer arithmetic.
The key features of the SIMPLE_INTEGER predefined subtype are the following:
• Includes the range of –2147483648.. +2147483648
• Has a not null constraint
• Wraps rather than overflows
• Is faster than PLS_INTEGER
Without the overhead of overflow checking and nullness checking, the SIMPLE_INTEGER
data type provides significantly better performance than PLS_INTEGER when the parameter
PLSQL_CODE_TYPE is set to native, because arithmetic operations on the former are
performed directly in the machine’s hardware. The performance difference is less noticeable
when the parameter PLSQL_CODE_TYPE is set to interpreted but even with this setting,
the SIMPLE_INTEGER type is faster than the PLS_INTEGER type.
SYSTOOLS
• Limit the number of lines of code between a BEGIN and END
to about a page or 60 lines of code.
• Use packaged programs to keep each executable section
small.
• Use local procedures and functions to hide logic.
• Use a function interface to hide formulas and business rules.
SYSTOOLS
9 - 18 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
small. This makes it easier for you to debug and refine your code.
SYSTOOLS
Each has its own benefits:
• SQL:
– Accesses data in the database
– Treats data as sets
• PL/SQL:
– Provides procedural capabilities
– Has more flexibility built into the language
SYSTOOLS
9 - 19 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
languages are absent in SQL, but present in PL/SQL. When using SQL in your PL/SQL
applications, be sure not to repeat a SQL statement. Instead, encapsulate your SQL statements in
a package and make calls to the package.
Using PL/SQL, you can take advantage of the PL/SQL-specific enhancements for SQL, such as
autonomous transactions, fetching into cursor records, using a cursor FOR loop, using the
RETURNING clause for information about modified rows, and using BULK COLLECT to
improve the performance of multiple-row queries.
Though there are advantages of using PL/SQL over SQL in several cases, use PL/SQL with
caution, especially under the following circumstances:
• Performing high-volume inserts
• Using user-defined PL/SQL functions
• Using external procedure calls
• Using the utl_file package as an alternative to SQL*Plus in high-volume reporting
SYSTOOLS
• Some simple set processing is markedly faster than the
equivalent PL/SQL.
BEGIN
INSERT INTO inventories2
SELECT product_id, warehouse_id
FROM main_inventories;
END;
• Avoid using procedural code when it may be better to
use SQL.
...FOR I IN 1..5600 LOOP
counter := counter + 1;
SYSTOOLS
SELECT product_id, warehouse_id
INTO v_p_id, v_wh_id
FROM big_inventories WHERE v_p_id = counter;
INSERT INTO inventories2 VALUES(v_p_id, v_wh_id);
END LOOP;...
SYSTOOLS
However, there are occasions when you will get better performance from PL/SQL, even when
the process could be written in SQL. Correlated updates are slow. With correlated updates, a
better method is to access only correct rows by using PL/SQL. The following PL/SQL loop is
faster than the equivalent correlated update SQL statement.
DECLARE
CURSOR cv_raise IS
SELECT deptno, increase
FROM emp_raise;
BEGIN
FOR dept IN cv_raise LOOP
UPDATE big_emp
SET sal = sal * dept.increase
WHERE deptno = dept.deptno;
END LOOP;
...
SYSTOOLS
• Instead of:
...
INSERT INTO order_items
(order_id, line_item_id, product_id,
unit_price, quantity)
VALUES (...
SYSTOOLS
• Or a packaged procedure:
orderitems.ins (
2458, 6, 3515, 2.00, 4);
SYSTOOLS
use the same INSERT statement, your application will run faster because of less parsing
and reduced demands on the System Global Area (SGA) memory.
• Your program will also handle data manipulation language (DML) errors consistently.
Cons
• You may need to write more procedural code.
• You may need to write several variations of update or insert procedures to handle the
combinations of columns that you are updating or inserting into.
SYSTOOLS
Use bulk binds to reduce context switches between the PL/SQL
engine and the SQL engine.
SYSTOOLS
(OrderId(j), executor executor
OrderDate(j), …);
SYSTOOLS
Improved Performance
Bulk binding enables you to implement array fetching. With bulk binding, entire collections, not
just individual elements, are passed back and forth. Bulk binding can be used with nested tables,
varrays, and associative arrays.
The more the rows affected by a SQL statement, the greater is the performance gain with bulk
binding.
SYSTOOLS
Bind whole arrays of values simultaneously, rather than looping
to perform fetch, insert, update, and delete on multiple rows.
• Instead of:
...
FOR i IN 1 .. 50000 LOOP
INSERT INTO bulk_bind_example_tbl
VALUES(...);
END LOOP; ...
• Use:
...
FORALL i IN 1 .. 50000
SYSTOOLS
INSERT INTO bulk_bind_example_tbl
VALUES(...);
...
SYSTOOLS
First, create the demonstration table:
CREATE TABLE bulk_bind_example_tbl (
num_col NUMBER,
date_col DATE,
char_col VARCHAR2(40));
Second, set the SQL*Plus TIMING variable on. Setting it on enables you to see the approximate
elapsed time of the last SQL statement:
SET TIMING ON
Third, run this block of code that includes a FOR loop to insert 50,000 rows:
DECLARE
TYPE typ_numlist IS TABLE OF NUMBER;
TYPE typ_datelist IS TABLE OF DATE;
TYPE typ_charlist IS TABLE OF VARCHAR2(40)
INDEX BY PLS_INTEGER;
-- continued on the next page
Oracle Database 11g: Advanced PL/SQL 9 - 23
Using Bulk Binding (continued)
-- continued from previous page
SYSTOOLS
n typ_numlist := typ_numlist();
d typ_datelist := typ_datelist();
c typ_charlist;
BEGIN
FOR i IN 1 .. 50000 LOOP
n.extend;
n(i) := i;
d.extend;
d(i) := sysdate + 1;
c(i) := lpad(1, 40);
END LOOP;
FOR I in 1 .. 50000 LOOP
INSERT INTO bulk_bind_example_tbl
VALUES (n(i), d(i), c(i));
END LOOP;
SYSTOOLS
END;
/
2.184ms elapsed
Last, run this block of code that includes a FORALL loop to insert 50,000 rows. Note the
significant decrease in the timing when using the FORALL processing:
DECLARE
TYPE typ_numlist IS TABLE OF NUMBER;
TYPE typ_datelist IS TABLE OF DATE;
TYPE typ_charlist IS TABLE OF VARCHAR2(40)
INDEX BY PLS_INTEGER;
n typ_numlist := typ_numlist();
d typ_datelist := typ_datelist();
c typ_charlist;
SYSTOOLS
BEGIN
FOR i IN 1 .. 50000 LOOP
n.extend;
n(i) := i;
d.extend;
d(i) := sysdate + 1;
c(i) := lpad(1, 40);
END LOOP;
FORALL I in 1 .. 50000
INSERT INTO bulk_bind_example_tbl
VALUES (n(i), d(i), c(i));
END;
/
828ms elapsed
SYSTOOLS
Use BULK COLLECT to improve performance:
CREATE OR REPLACE PROCEDURE process_customers
(p_account_mgr customers.account_mgr_id%TYPE)
IS
TYPE typ_numtab IS TABLE OF
customers.customer_id%TYPE;
TYPE typ_chartab IS TABLE OF
customers.cust_last_name%TYPE;
TYPE typ_emailtab IS TABLE OF
customers.cust_email%TYPE;
v_custnos typ_numtab;
v_last_names typ_chartab;
v_emails typ_emailtab;
BEGIN
SYSTOOLS
SELECT customer_id, cust_last_name, cust_email
BULK COLLECT INTO v_custnos, v_last_names, v_emails
FROM customers
WHERE account_mgr_id = p_account_mgr;
...
END process_customers;
SYSTOOLS
You can use the BULK COLLECT option with explicit cursors too:
BEGIN
OPEN cv_customers INTO customers_rec;
FETCH cv_customers BULK COLLECT INTO
v_custnos, v_last_name, v_mails;
...
You can also use the LIMIT option with BULK COLLECT. This gives you control over the
amount of processed rows in one step.
FETCH cv_customers BULK COLLECT
INTO v_custnos, v_last_name, v_email
LIMIT 200;
SYSTOOLS
Use the RETURNING clause to retrieve information about the
rows that are being modified:
DECLARE
TYPE typ_replist IS VARRAY(100) OF NUMBER;
TYPE typ_numlist IS TABLE OF
orders.order_total%TYPE;
repids typ_replist :=
typ_replist(153, 155, 156, 161);
totlist typ_numlist;
c_big_total CONSTANT NUMBER := 60000;
BEGIN
FORALL i IN repids.FIRST..repids.LAST
UPDATE orders
SYSTOOLS
SET order_total = .95 * order_total
WHERE sales_rep_id = repids(i)
AND order_total > c_big_total
RETURNING order_total BULK COLLECT INTO Totlist;
END;
SYSTOOLS
same time, collect information about the data being changed. As a result, fewer network round
trips, less server CPU time, fewer cursors, and less server memory are required. Without the
RETURNING clause, you need two operations: one to make the change, and a second operation
to retrieve information about the change. In the slide example, the order_total information
is retrieved from the ORDERS table and collected into the totlist collection. The totlist
collection is returned in bulk to the PL/SQL engine.
If you did not use the RETURNING clause, you would need to perform two operations, one for
the UPDATE, and another for the SELECT:
UPDATE orders SET order_total = .95 * order_total
WHERE sales_rep_id = p_id
AND order_total > c_big_total;
SYSTOOLS
the customer’s new credit limit into a SQL Developer environment variable:
CREATE OR REPLACE PROCEDURE change_credit
(p_in_id IN customers.customer_id%TYPE,
o_credit OUT NUMBER)
IS
BEGIN
UPDATE customers
SET credit_limit = credit_limit * 1.10
WHERE customer_id = p_in_id
RETURNING credit_limit INTO o_credit;
END change_credit;
/
VARIABLE g_credit NUMBER
EXECUTE change_credit(109, :g_credit)
PRINT g_credit
SYSTOOLS
SYSTOOLS
SYSTOOLS
• You can use the SAVE EXCEPTIONS keyword in your
FORALL statements:
FORALL index IN lower_bound..upper_bound
SAVE EXCEPTIONS
{insert_stmt | update_stmt | delete_stmt}
SYSTOOLS
ERROR_INDEX Holds the iteration of the FORALL statement where the
exception was raised
SYSTOOLS
All exceptions raised during the execution are saved in the %BULK_EXCEPTIONS cursor
attribute, which stores a collection of records. This cursor attribute is available only from the
exception handler.
Each record has two fields. The first field, %BULK_EXCEPTIONS(i).ERROR_INDEX, holds
the “iteration” of the FORALL statement during which the exception was raised. The second
field, BULK_EXCEPTIONS(i).ERROR_CODE, holds the corresponding Oracle error code.
The values stored by %BULK_EXCEPTIONS always refer to the most recently executed
FORALL statement. The number of exceptions is saved in the count attribute of
%BULK_EXCEPTIONS; that is, %BULK_EXCEPTIONS.COUNT. Its subscripts range from 1 to
COUNT. If you omit the SAVE EXCEPTIONS keyword, execution of the FORALL statement
stops when an exception is raised. In that case, SQL%BULK_EXCEPTIONS.COUNT returns 1,
and SQL%BULK_EXCEPTIONS contains just one record. If no exception is raised during the
execution, SQL%BULK_EXCEPTIONS.COUNT returns 0.
DECLARE
SYSTOOLS
TYPE NumList IS TABLE OF NUMBER;
num_tab NumList :=
NumList(100,0,110,300,0,199,200,0,400);
bulk_errors EXCEPTION;
PRAGMA EXCEPTION_INIT (bulk_errors, -24381 );
BEGIN
FORALL i IN num_tab.FIRST..num_tab.LAST
SAVE EXCEPTIONS
DELETE FROM orders WHERE order_total < 500000/num_tab(i);
EXCEPTION WHEN bulk_errors THEN
DBMS_OUTPUT.PUT_LINE('Number of errors is: '
|| SQL%BULK_EXCEPTIONS.COUNT);
FOR j in 1..SQL%BULK_EXCEPTIONS.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE (
SYSTOOLS
TO_CHAR(SQL%BULK_EXCEPTIONS(j).error_index) ||
' / ' ||
SQLERRM(-SQL%BULK_EXCEPTIONS(j).error_code) );
END LOOP;
END;
/
Example
In this example, the EXCEPTION_INIT pragma defines an exception named BULK_ERRORS
and associates the name with the ORA-24381 code, which is an “Error in Array DML.”
The PL/SQL block raises the predefined exception ZERO_DIVIDE when i equals 2, 5, 8. After
the bulk bind is completed, SQL%BULK_EXCEPTIONS.COUNT returns 3, because the code
SYSTOOLS
tried to divide by zero three times. To get the Oracle error message (which includes the code),
you pass SQL%BULK_EXCEPTIONS(i).ERROR_CODE to the error-reporting function
SQLERRM. Here is the output:
Number of errors is: 5
Number of errors is: 3
2 / ORA-01476: divisor is equal to zero
5 / ORA-01476: divisor is equal to zero
8 / ORA-01476: divisor is equal to zero
• Scenario 2:
IF credit_ok(cust_id) AND (v_order_total < 5000) THEN
SYSTOOLS
...
END IF;
SYSTOOLS
operand (because OR returns TRUE if either of its operands is true).
Now, consider the second scenario in the slide, which involves an AND expression. The Boolean
function CREDIT_OK is always called. However, if you switch the operands of AND as follows,
the function is called only when the expression v_order_total < 5000 is true (because
AND returns TRUE only if both its operands are true):
IF (v_order_total < 5000 ) AND credit_ok(cust_id) THEN
...
END IF;
SYSTOOLS
END IF; ELSIF v_acct_mgr = 149
IF v_acct_mgr = 149 THEN THEN
process_acct_149; process_acct_149;
END IF; END IF;
SYSTOOLS
on the left, after a branch is found to be true, the rest of the branch conditions are not evaluated.
Sometimes you do not need an IF statement. For example, the following code can be rewritten
without an IF statement:
IF date_ordered < sysdate + 7 THEN
late_order := TRUE;
ELSE
late_order := FALSE;
END IF;
SYSTOOLS
• The flexibility built into PL/SQL enables you to pass:
– Simple scalar variables
– Complex data structures
• You can use the NOCOPY hint to improve performance with
the IN OUT parameters.
SYSTOOLS
9 - 32 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
experience significantly more overhead, because a copy of the parameter value is stored before
the routine is executed. The stored value must be kept in case an exception occurs. You can use
the NOCOPY compiler hint to improve performance in this situation. NOCOPY instructs the
compiler not to make a backup copy of the parameter that is being passed. However, be careful
when you use the NOCOPY compiler hint, because your results are not predictable if your
program encounters an exception.
SYSTOOLS
Pass records as parameters to encapsulate data, as well as,
write and maintain less code:
DECLARE
TYPE CustRec IS RECORD (
customer_id customers.customer_id%TYPE,
cust_last_name VARCHAR2(20),
cust_email VARCHAR2(30),
credit_limit NUMBER(9,2));
...
PROCEDURE raise_credit (cust_info CustRec);
SYSTOOLS
9 - 33 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
When you call a function that returns a record, use the notation:
function_name(parameters).field_name
For example, the following call to the NTH_HIGHEST_ORD_TOTAL function references the
ORDER_TOTAL field in the ORD_INFO record:
DECLARE
TYPE OrdRec IS RECORD (
v_order_id NUMBER(6),
v_order_total REAL);
v_middle_total REAL;
FUNCTION nth_highest_total (n INTEGER) RETURN OrdRec IS
order_info OrdRec;
BEGIN ...
RETURN order_info; -- return record
END;
BEGIN -- call function
v_middle_total := nth_highest_total(10).v_order_total;
...
Oracle Database 11g: Advanced PL/SQL 9 - 33
Passing Data Between PL/SQL Programs
SYSTOOLS
Use collections as arguments:
PACKAGE cust_actions IS
TYPE NameTabTyp IS TABLE OF
customer.cust_last_name%TYPE
INDEX BY PLS_INTEGER;
TYPE CreditTabTyp IS TABLE OF
customers.credit_limit%TYPE
INDEX BY PLS_INTEGER;
...
PROCEDURE credit_batch( name_tab IN NameTabTyp ,
credit_tab IN CreditTabTyp,
...);
SYSTOOLS
PROCEDURE log_names ( name_tab IN NameTabTyp );
END cust_actions;
SYSTOOLS
SYSTOOLS
• Using native and interpreted compilation methods
• Tuning PL/SQL code
• Enabling intraunit inlining
SYSTOOLS
9 - 35 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• Definition:
– Inlining is the replacement of a call to a subroutine with a copy
of the body of the subroutine that is called.
– The copied procedure generally runs faster than the original.
– The PL/SQL compiler can automatically find the calls that
should be inlined.
• Benefits:
– Inlining can provide large performance gains when applied
judiciously by a factor of 2–10 times.
SYSTOOLS
9 - 36 Copyright © 2008, Oracle. All rights reserved.
Introducing Inlining
Procedure inlining is an optimization process that replaces procedure calls with a copy of the
body of the procedure to be called. The copied procedure almost always runs faster than the
original call, because:
• The need to create and initialize the stack frame for the called procedure is eliminated.
SYSTOOLS
• The optimization can be applied over the combined text of the call context and the copied
procedure body.
• Propagation of constant actual arguments often causes the copied body to collapse under
optimization.
When inlining is achieved, you can see performance gains of 2–10 times.
With Oracle Database 11g, the PL/SQL compiler can automatically find calls that should be
inlined, and can do the inlining correctly and quickly. There are some controls to specify where
and when the compiler should do this work (using the PLSQL_OPTIMIZATION_LEVEL
database parameter), but usually, a general request is sufficient.
SYSTOOLS
• Influence implementing inlining via two methods:
– Oracle parameter PLSQL_OPTIMIZE_LEVEL
– PRAGMA INLINE
• Recommend that you:
– Inline small programs
– Inline programs that are frequently executed
• Use performance tools to identify the hotspots that are
suitable for inline applications:
– plstimer
SYSTOOLS
9 - 37 Copyright © 2008, Oracle. All rights reserved.
Using Inlining
When implementing inlining, it is recommended that the process be applied to smaller programs,
and/or programs that execute frequently. For example, you may want to inline small helper
programs.
To help you identify which programs to inline, you can use the plstimer PL/SQL
SYSTOOLS
performance tool. This tool specifically analyzes program performance in terms of the time
spent in procedures and the time spent on particular call sites. It is important that you identify
the procedure calls that may benefit from inlining.
There are two ways to use inlining:
1. Set the PLSQL_OPTIMIZE_LEVEL parameter to 3. When this parameter is set to 3, the
PL/SQL compiler searches for calls that might profit from inlining and inlines the most
profitable calls. Profitability is measured by those calls that help the program speed up the
most and keep the compiled object program as short as possible.
ALTER SESSION SET plsql_optimize_level = 3;
2. Use PRAGMA INLINE in your PL/SQL code. This identifies whether a specific call should
be inlined. Setting this pragma to “YES” has an effect only if the optimize level is set to
two or higher.
SYSTOOLS
Noninlined program:
CREATE OR REPLACE PROCEDURE small_pgm
IS
a NUMBER;
b NUMBER;
SYSTOOLS
BEGIN
a := b;
FOR I IN 1..10 LOOP
touch(a, -17);
a := a*b;
END LOOP;
END small_pgm;
Inlining Concepts
The example shown in the slide will be expanded to show you how a procedure is inlined.
The a:=a*b assignment at the end of the loop looks like it could be moved before the loop.
However, it cannot be, because a is passed as an IN OUT parameter to the TOUCH procedure.
The compiler cannot be certain what the procedure does to its parameters. This results in the
SYSTOOLS
multiplication and in the assignment’s being completed 10 times instead of only once, even
though multiple executions are not necessary.
SYSTOOLS
Examine the loop after inlining:
...
BEGIN
a := b;
FOR i IN 1..10 LOOP
IF –17 > 0 THEN
a := a*a;
END IF;
a := a*b;
END LOOP;
END small_pgm;
...
SYSTOOLS
9 - 39 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
The loop is transformed in several steps:
a := b;
FOR i IN 1..10 LOOP ...
IF false THEN
a := a*a;
END IF;
a := a*b;
END LOOP;
a := b;
FOR i IN 1..10 LOOP ...
a := a*b;
END LOOP;
a := b;
SYSTOOLS
a := a*b;
FOR i IN 1..10 LOOP ...
END LOOP;
a := b*b;
FOR i IN 1..10 LOOP ...
END LOOP;
SYSTOOLS
would be a million assignments. For code that contains deep loops that are executed frequently,
inlining offers tremendous savings.
SYSTOOLS
• Set the PLSQL_OPTIMIZE_LEVEL session-level parameter
to a value of 2 or 3:
ALTER PROCEDURE small_pgm COMPILE
PLSQL_OPTIMIZE_LEVEL = 3 REUSE SETTINGS;
SYSTOOLS
regardless of the YES pragmas.
– YES means inline at level 2 of a particular call and increase
the priority of inlining at level 3 for the call.
SYSTOOLS
might profit from inlining and inlines the most profitable calls.
In rare cases, if the overhead of the optimizer makes the compilation of very large applications
take too long, you can lower the optimization by setting PLSQL_OPTIMIZE_LEVEL=1
instead of its default value of 2. In even rarer cases, you might see a change in exception action,
either an exception that is not raised at all, or one that is raised earlier than expected. Setting
PLSQL_OPTIMIZE_LEVEL=1 prevents the code from being rearranged.
To enable inlining within a PL/SQL subroutine, you can use PRAGMA INLINE to suggest that a
specific call be inlined.
SYSTOOLS
After setting the PLSQL_OPTIMIZE_LEVEL parameter, use a
pragma:
CREATE OR REPLACE PROCEDURE small_pgm
IS
a PLS_INTEGER;
FUNCTION add_it(a PLS_INTEGER, b PLS_INTEGER)
RETURN PLS_INTEGER
IS
BEGIN
RETURN a + b;
END;
BEGIN
SYSTOOLS
pragma INLINE (add_it, 'YES');
a := add_it(3, 4) + 6;
END small_pgm;
SYSTOOLS
wrong place, you receive a syntax error message from the compiler.
To identify that a specific call should not be inlined, use:
PRAGMA INLINE (function_name, 'NO');
Setting the PRAGMA INLINE to ‘NO’ always works, regardless of any other pragmas that might
also apply to the same statement. The pragma also applies at all optimization levels, and it
applies no matter how badly the compiler would like to inline a particular call. If you are certain
that you do not want some code inlined (perhaps due to the large size), you can set this to NO.
Setting the PRAGMA INLINE to ‘YES’ strongly encourages the compiler to inline the call. The
compiler keeps track of the resources used during inlining and makes the decision to stop
inlining when the cost becomes too high.
If inlining is requested and you have the compiler warnings turned on, you see the message:
PLW-06004: inlining of call of procedure ADD_IT requested.
If inlining is applied, you see the compiler warning (it is more of a message):
PLW-06005: inlining of call of procedure 'ADD_IT' was done.
Oracle Database 11g: Advanced PL/SQL 9 - 42
Inlining: Guidelines
SYSTOOLS
• Pragmas apply only to calls in the next statement following
the pragma.
• Programs that make use of smaller helper subroutines are
good candidates for inlining.
• Only local subroutines can be inlined.
• You cannot inline an external subroutine.
• Inlining can increase the size of a unit.
• Be careful about suggesting to inline functions that are
deterministic.
SYSTOOLS
9 - 43 Copyright © 2008, Oracle. All rights reserved.
Inlining: Guidelines
The compiler inlines code automatically, provided that you are using native compilation and
have set the PLSQL_OPTIMIZE_LEVEL to 3. If you have set PLSQL_Warnings =
'enable:all', using the SQL*Plus SHOW ERRORS command displays the name of the code
that is inlined.
SYSTOOLS
• The PLW-06004 compiler message tells you that a pragma INLINE('YES') referring
to the named procedure was found. The compiler will, if possible, inline this call.
• The PLW-06005 compiler message tells you the name of the code that is inlined.
Alternatively, you can query the USER/ALL/DBA_ERRORS dictionary view.
Deterministic functions compute the same outputs for the same inputs every time it is invoked
and have no side effects. In Oracle Database 11g, the PL/SQL compiler can figure out whether a
function is deterministic; it may not find all that truly are, but it finds many of them. It never
mistakes a nondeterministic function for a deterministic function.
SYSTOOLS
In this lesson, you should have learned how to:
• Decide when to use native or interpreted compilation
• Tune your PL/SQL application. Tuning involves:
– Using the RETURNING clause and bulk binds
when appropriate
– Rephrasing conditional statements
– Identifying data type and constraint issues
– Understanding when to use SQL and PL/SQL
• Identify opportunities for inlining PL/QL code
SYSTOOLS
• Use native compilation for faster PL/SQL execution
Summary
There are several methods that help you tune your PL/SQL application.
When tuning PL/SQL code, consider using the RETURNING clause and/or bulk binds to
improve processing. Be aware of conditional statements with an OR clause. Place the fastest
processing condition first. There are several data type and constraint issues that can help in
SYSTOOLS
tuning an application.
By using native compilation, you can benefit from performance gains for computation-intensive
procedural operations.
SYSTOOLS
This practice covers the following topics:
• Tuning PL/SQL code to improve performance
• Coding with bulk binds to improve performance
SYSTOOLS
9 - 45 Copyright © 2008, Oracle. All rights reserved.
Practice 9: Overview
In this practice, you tune some of the code that you created for the OE application.
• Break a previously built subroutine into smaller executable sections
• Pass collections into subroutines
• Add error handling for BULK INSERT
SYSTOOLS
Use the OE schema for this practice.
For detailed instructions about performing this practice, see Appendix A, “Practice Solutions.”
SYSTOOLS
Writing Better Code
1. Open the lab_09_01.sql file and examine the package (the package body is shown
below):
CREATE OR REPLACE PACKAGE credit_card_pkg
IS
PROCEDURE update_card_info
(p_cust_id NUMBER, p_card_type VARCHAR2, p_card_no
VARCHAR2);
PROCEDURE display_card_info
(p_cust_id NUMBER);
END credit_card_pkg; -- package spec
/
SYSTOOLS
PROCEDURE update_card_info
(p_cust_id NUMBER, p_card_type VARCHAR2, p_card_no
VARCHAR2)
IS
v_card_info typ_cr_card_nst;
i INTEGER;
BEGIN
SELECT credit_cards
INTO v_card_info
FROM customers
WHERE customer_id = p_cust_id;
SYSTOOLS
SYSTOOLS
IF v_card_info.EXISTS(1) THEN -- cards exist, add more
i := v_card_info.LAST;
v_card_info.EXTEND(1);
v_card_info(i+1) := typ_cr_card(p_card_type,
p_card_no);
UPDATE customers
SET credit_cards = v_card_info
WHERE customer_id = p_cust_id;
ELSE -- no cards for this customer yet, construct one
UPDATE customers
SET credit_cards = typ_cr_card_nst
(typ_cr_card(p_card_type, p_card_no))
WHERE customer_id = p_cust_id;
END IF;
END update_card_info;
SYSTOOLS
PROCEDURE display_card_info
(p_cust_id NUMBER)
IS
v_card_info typ_cr_card_nst;
i INTEGER;
BEGIN
SELECT credit_cards
INTO v_card_info
FROM customers
WHERE customer_id = p_cust_id;
IF v_card_info.EXISTS(1) THEN
FOR idx IN v_card_info.FIRST..v_card_info.LAST LOOP
DBMS_OUTPUT.PUT('Card Type: ' ||
v_card_info(idx).card_type || ' ');
DBMS_OUTPUT.PUT_LINE('/ Card No: ' ||
v_card_info(idx).card_num );
SYSTOOLS
END LOOP;
ELSE
DBMS_OUTPUT.PUT_LINE('Customer has no credit cards.');
END IF;
END display_card_info;
END credit_card_pkg; -- package body
/
This code needs to be improved. The following issues exist in the code:
• The local variables use the INTEGER data type.
• The same SELECT statement is run in the two procedures.
• The same IF v_card_info.EXISTS(1) THEN statement is in the two procedures.
SYSTOOLS
2. To improve the code, make the following modifications:
a. Change the local INTEGER variables to use a more efficient data type.
b. Move the duplicated code into a function. The package specification for the
modification is:
CREATE OR REPLACE PACKAGE credit_card_pkg
IS
FUNCTION cust_card_info
(p_cust_id NUMBER, p_card_info IN OUT typ_cr_card_nst )
RETURN BOOLEAN;
PROCEDURE update_card_info
(p_cust_id NUMBER, p_card_type VARCHAR2, p_card_no
VARCHAR2);
PROCEDURE display_card_info
SYSTOOLS
(p_cust_id NUMBER);
END credit_card_pkg; -- package spec
/
c. Have the function return TRUE if the customer has credit cards. The function should
return FALSE if the customer does not have credit cards. Pass an uninitialized nested
table into the function. The function places the credit card information into this
uninitialized parameter.
EXECUTE credit_card_pkg.display_card_info(120)
Card Type: Visa / Card No: 11111111
Card Type: MC / Card No: 2323232323
SYSTOOLS
Card Type: DC / Card No: 4444444
Card Type: AM EX / Card No: 55555555555
EXECUTE credit_card_pkg.display_card_info(120)
Card Type: AM EX / Card No: 55555555555
SYSTOOLS
RETURNING clause) about the credit cards being updated. Assume that this information
will be used by another application developer in your team, who is writing a graphical
reporting utility on customer credit cards.
a. Open the lab_09_04_a.sql file. It contains the modified code from the previous
question #2.
b. Modify the code to use the RETURNING clause to find information about the rows
that are affected by the UPDATE statements.
c. You can test your modified code with the following procedure (contained in
lab_09_04_c.sql):
SYSTOOLS
v_card_info typ_cr_card_nst;
BEGIN
credit_card_pkg.update_card_info
(p_cust_id, p_card_type, p_card_no, v_card_info);
END test_credit_update_info;
/
SYSTOOLS
SYSTOOLS
5. In this exercise, you test exception handling with the SAVE EXCEPTIONS clause.
a. Run the lab_09_05a.sql file to create a test table:
CREATE TABLE card_table
(accepted_cards VARCHAR2(50) NOT NULL);
SYSTOOLS
SAVE EXCEPTIONS
EXECUTE IMMEDIATE
'insert into card_table (accepted_cards) values (
:the_card)'
USING v_cards(j);
END;
/
SYSTOOLS
SYSTOOLS
DECLARE
type typ_cards is table of VARCHAR2(50);
v_cards typ_cards := typ_cards
( 'Citigroup Visa', 'Nationscard MasterCard',
'Federal American Express', 'Citizens Visa',
'International Discoverer', 'United Diners Club' );
bulk_errors EXCEPTION;
PRAGMA exception_init (bulk_errors, -24381 );
BEGIN
v_cards.Delete(3);
v_cards.DELETE(6);
FORALL j IN v_cards.first..v_cards.last
SAVE EXCEPTIONS
EXECUTE IMMEDIATE
'insert into card_table (accepted_cards) values (
SYSTOOLS
:the_card)'
USING v_cards(j);
EXCEPTION
WHEN bulk_errors THEN
FOR j IN 1..sql%bulk_exceptions.count
LOOP
Dbms_Output.Put_Line (
TO_CHAR( sql%bulk_exceptions(j).error_index ) || ':
' || SQLERRM(-sql%bulk_exceptions(j).error_code) );
END LOOP;
END;
/
SYSTOOLS
SYSTOOLS
6. In this exercise, you compare the performance between the PLS_INTEGER and
SIMPLE_INTEGER data types with native compilation:
SYSTOOLS
SUBTYPE My_Integer_t IS PLS_INTEGER;
My_Integer_t_Name CONSTANT VARCHAR2(30) := 'PLS_INTEGER';
$END
BEGIN
t0 := DBMS_UTILITY.GET_CPU_TIME();
WHILE v01 < lmt LOOP
v00 := v00 + Two;
v01 := v01 + Two;
SYSTOOLS
v02 := v02 + Two;
v03 := v03 + Two;
v04 := v04 + Two;
v05 := v05 + Two;
END LOOP;
t1 := DBMS_UTILITY.GET_CPU_TIME();
DBMS_OUTPUT.PUT_LINE(
RPAD(LOWER($$PLSQL_Code_Type), 15)||
RPAD(LOWER(My_Integer_t_Name), 15)||
TO_CHAR((t1-t0), '9999')||' centiseconds');
END p;
SYSTOOLS
PLSQL_Code_Type = NATIVE PLSQL_CCFlags = 'simple:true'
REUSE SETTINGS;
EXECUTE p()
EXECUTE p()
SYSTOOLS
SYSTOOLS
SYSTOOLS
SYSTOOLS
SYSTOOLS
Improving Performance with Caching
SYSTOOLS
Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Objectives
SYSTOOLS
After completing this lesson, you should be able to do the
following:
• Improve memory usage by caching SQL result sets
• Write queries that use the result cache hint
• Use the DBMS_RESULT_CACHE package
• Set up PL/SQL functions to use PL/SQL result caching
SYSTOOLS
10 - 2 Copyright © 2008, Oracle. All rights reserved.
Objectives
In this lesson, you learn about the Oracle Database 11g caching techniques that can improve
performance. You examine the improvement on the performance of queries by caching the results of
a query in memory, and then using the cached results in future executions of the query or query
fragments. The cached results reside in the result cache memory portion of the shared global area
SYSTOOLS
(SGA).
The PL/SQL cross-section function result caching mechanism provides applications with a language-
supported and system-managed means for storing the results of PL/SQL functions in an SGA, which
is available to every session that runs the application.
SYSTOOLS
• Improving memory usage by caching SQL result sets
– Enabling Query Result Cache
– Using the DBMS_RESULT_CACHE package
• Implementing SQL Query Result Cache
– Writing queries that use the result cache hint
• Using PL/SQL Function Result Cache
– Setting up PL/SQL functions to use PL/SQL result caching
– Implementing PL/SQL Function Result Caching
SYSTOOLS
10 - 3 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• Result Cache allows SQL query and PL/SQL function results
to be stored in cache memory.
• Subsequent executions of the same query or function can be
served directly out of the cache, improving response times.
• This technique can be especially effective for SQL queries
and PL/SQL functions that are executed frequently.
• Cached query results become invalid when the database
data accessed by the query is modified.
SGA Shared pool
SYSTOOLS Library
cache
Data dictionary
cache
Result
cache
SYSTOOLS
data in the database objects being accessed by the query are modified.
SYSTOOLS
• You can increase the small, default result cache memory
size by using the RESULT_CACHE_MAX_SIZE initialization
parameter.
SGA
Shared pool
Default
result
cache
Increased
SYSTOOLS
result
cache
SYSTOOLS
Oracle allocates 0.25% of the memory target to the result cache.
• When you set the size of the shared pool using the SGA_TARGET initialization parameter,
Oracle allocates 0.5% of the SGA target to the result cache.
• If you specify the size of the shared pool using the SHARED_POOL_SIZE initialization
parameter, Oracle allocates 1% of the shared pool size to the result cache.
Note: Oracle will not allocate more than 75% of the shared pool to the result cache.
Use the RESULT_CACHE_MAX_RESULT initialization parameter to specify the maximum
percentage of result cache memory that can be used by any single result. The default value is 5%, but
you can specify any percent value between 1 and 100.
SYSTOOLS
• Set Result_Cache_Max_Size from the command line or
in an initialization file by a DBA.
• The cache size is dynamic and can be changed either
permanently or until the instance is restarted.
SYSTOOLS
NAME VALUE
---------------------------------------- ------------------
result_cache_max_size
1 row selected.
2097152
Setting Result_Cache_Max_Size
By default, the server-side Result Cache is configured to use a very small portion of the shared pool.
You can manually set the result cache memory size by using the RESULT_CACHE_MAX_SIZE
initialization parameter. Setting RESULT_CACHE_MAX_SIZE to 0 during database startup disables
the server-side Result Cache. RESULT_CACHE_MAX_SIZE cannot be dynamically changed if the
SYSTOOLS
value is set to 0 during database startup in the spfile or the init.ora file.
SYSTOOLS
• Use the RESULT_CACHE_MODE initialization parameter in the
database initialization parameter file.
• RESULT_CACHE_MODE can be set to:
– MANUAL (default): You must add the RESULT_CACHE hint to
your queries for the results to be cached.
– FORCE: Results are always stored in the Result Cache
Memory, if possible.
SYSTOOLS
10 - 7 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
• MANUAL (default): You must add the RESULT_CACHE hint to your queries for the results to be
cached or to be served out of the cache. The RESULT_CACHE hint can also be added in
subqueries and inline views.
• FORCE: Results are always stored in the Result Cache Memory, if possible.
The use of the SQL Query Result Cache introduces the ResultCache operator in the query execution
plan.
SYSTOOLS
• The DBMS_RESULT_CACHE package provides an interface
for a DBA to manage memory allocation for SQL query result
cache and the PL/SQL function result cache.
execute dbms_result_cache.memory_report
R e s u l t C a c h e M e m o r y R e p o r t
[Parameters]
Block Size = 1K bytes
Maximum Cache Size = 1056K bytes (1056 blocks)
Maximum Result Size = 52K bytes (52 blocks)
[Memory]
Total Memory = 5140 bytes [0.003% of the Shared Pool]
SYSTOOLS
... Fixed Memory = 5140 bytes [0.003% of the Shared Pool]
... Dynamic Memory = 0 bytes [0.000% of the Shared Pool]
R e s u l t
[Parameters]
Block Size SYSTOOLS
C a c h e M e m o r y
= 1K bytes
R e p o r t
SYSTOOLS
• Improving memory usage by caching SQL result sets
– Enabling Query Result Cache
– Using the DBMS_RESULT_CACHE package
• Implementing SQL Query Result Cache
– Writing queries that use the result cache hint
• Using PL/SQL Function Result Cache
– Setting up PL/SQL functions to use PL/SQL result caching
– Implementing PL/SQL Function Result Caching
SYSTOOLS
10 - 9 Copyright © 2008, Oracle. All rights reserved.
Lesson Agenda
An example of setting the result cache hint is provided on the next few pages.
SYSTOOLS
SYSTOOLS
• Definition:
– Cache the results of the current query or query fragment in
memory, and then use the cached results in future executions
of the query or query fragments.
– Cached results reside in the result cache memory portion of
the SGA.
• Benefits:
– Improved performance
SYSTOOLS
10 - 10 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
• Scenario:SYSTOOLS
– You need to find the greatest average value of credit limit
grouped by state over the whole population.
– The query results in a large number of rows being analyzed to
yield a few or one row.
– In your query, the data changes fairly slowly (say every hour)
but the query is repeated fairly often (say every second).
• Solution:
– Use the new optimizer hint /*+ result_cache */ in your
query:
SYSTOOLS
SELECT /*+ result_cache */
AVG(cust_credit_limit), cust_state_province
FROM sh.customers
GROUP BY cust_state_province;
Usage
SQL result caching is useful when your queries need to analyze a large number of rows to return a
small number of rows or a single row.
Two new optimizer hints are available to turn on and turn off SQL result caching:
/*+ result_cache */
SYSTOOLS
/*+ no_result_cache */
These hints enable you to override the settings of the RESULT_CACHE_MODE initialization
parameter.
You can execute DBMS_RESULT_CACHE.MEMORY_REPORT to produce a memory usage report of
the result cache.
SYSTOOLS
--- flush.sql
--- Start with a clean slate. Flush the cache and shared pool.
--- Verify that memory was released.
connect / as sysdba
SET ECHO ON
SET FEEDBACK 1
SET NUMWIDTH 10
SET LINESIZE 150
SET TRIMSPOOL ON
SET TAB OFF
SET PAGESIZE 1000
SET SERVEROUTPUT ON
execute dbms_result_cache.flush
alter system flush shared_pool
/
execute dbms_result_cache.memory_report
SYSTOOLS
10 - 12 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
--- flush.sql
--- Start with a clean slate. Flush the cache and shared pool.
--- Verify that memory was released.
connect / as sysdba
SET ECHO ON
SET FEEDBACK 1
SET NUMWIDTH 10
SET LINESIZE 150
SET TRIMSPOOL ON
SET TAB OFF
SET PAGESIZE 1000
SET SERVEROUTPUT ON
execute dbms_result_cache.flush
alter system flush shared_pool
/
execute dbms_result_cache.memory_report
R e s u l t C a c h e M e m o r y R e p o r t
[Parameters]
Block Size = 1K bytes
SYSTOOLS
Maximum Cache Size = 1056K bytes (1056 blocks)
Maximum Result Size = 52K bytes (52 blocks)
[Memory]
Total Memory = 5140 bytes [0.003% of the Shared Pool]
... Fixed Memory = 5140 bytes [0.003% of the Shared Pool]
... Dynamic Memory = 0 bytes [0.000% of the Shared Pool]
PL/SQL procedure successfully completed.
SYSTOOLS
SYSTOOLS
--- plan_query1.sql
connect oe
--- Generate the execution plan.
--- (The query name Q1 is optional)
explain plan for
select /*+ result_cache q_name(Q1) */ * from orders;
set echo off
--- Display the execution plan. Verify that the query result
--- is placed in the Result Cache.
@$ORACLE_HOME/rdbms/admin/utlxpls
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
----------------------------------------------------------------------
Plan hash value: 1275100350
--------------------------------------------------------------------------------
-----------------
| Id | Operation | Name | Rows | Bytes | Cost (
%CPU)| Time |
--------------------------------------------------------------------------------
-----------------
| 0 | SELECT STATEMENT | | 105 | 3885 | 3
(0)| 00:00:01 |
| 1 | RESULT CACHE | 5f0x59rau680n60zdua0mztzku | | |
SYSTOOLS
| |
| 2 | TABLE ACCESS FULL| ORDERS | 105 | 3885 | 3
(0)| 00:00:01 |
--------------------------------------------------------------------------------
-----------------
Result Cache Information (identified by operation id):
------------------------------------------------------
1 - column-count=8; dependencies=(OE.ORDERS);
name="select /*+ result_cache q_name(Q1) */ * from orders"
14 rows selected.
SYSTOOLS
SYSTOOLS
--- plan_query2.sql
set echo on
connect oe PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
--- Generate the execution plan.
----------------------------------------------------------------------
Plan hash value: 2892511806
--- (The query name Q2 is optional)
explain plan for --------------------------------------------------------------------------------
select c.customer_id, o.ord_count
------------------
| Id q_name(Q2)
from (select /*+ result_cache | Operation */ | Name | Rows | Bytes | Cost
(%CPU)| Time |
customer_id, count(*) --------------------------------------------------------------------------------
ord_count
from orders ------------------
group by customer_id) |o,(0)|
0customers
| SELECT STATEMENT
00:00:01 | c
| | 47 | 1692 | 1
where o.customer_id = c.customer_id;
| 1 | NESTED LOOPS | | 47 | 1692 | 1
(0)| 00:00:01 |
set echo off |*
2 | VIEW | | 47 | 1316 | 1
(0)| 00:00:01 |
| 3 | RESULT CACHE | 2za8xzq061xnu8q8m2r14d1s23 | | |
--- Display the execution plan. | |
--- using the code in | 4 | HASH GROUP BY | | 47 | 188 | 1
(0)| 00:00:01 |
ORACLE_HOME/rdbms/admin/utlxpls
| 5 | INDEX FULL SCAN| ORD_CUSTOMER_IX | 105 | 420 | 1
(0)| 00:00:01 |
|* 6 | INDEX
set markup html preformat on (0)| 00:00:01 |UNIQUE SCAN | CUSTOMERS_PK | 1 | 8 | 0
--------------------------------------------------------------------------------
select plan_table_output from
------------------
table(dbms_xplan.display('plan_table',
Predicate Information (identified by operation id):
null,'serial')); ---------------------------------------------------
SYSTOOLS
2 - filter("O"."CUSTOMER_ID">0)
6 - access("O"."CUSTOMER_ID"="C"."CUSTOMER_ID")
filter("C"."CUSTOMER_ID">0)
Result Cache Information (identified by operation id):
------------------------------------------------------
3 - column-count=2; dependencies=(OE.ORDERS);
name="select /*+ result_cache q_name(Q2) */
customer_id, count(*) ord_count
from orders
group by customer_id"
SYSTOOLS
--- query3.sql
connect oe
set echo on
SYSTOOLS
--- Cache result of both queries, then use the cached result.
. . . .
2453 04-OCT-99 06.53.34.362632 PM
direct 116 0 129 153
select /*+ result_cache q_name(Q1) */ * from orders
/ 2456 07-NOV-98 06.53.25.989889 PM
direct 117 0 3878.4 163
SYSTOOLS
CUSTOMER_ID ORD_COUNT
----------- ----------
123 1
151 1
152 1
153 1
167 1
168 1
116 4
120 1
121 1
144 5
. . . .
SYSTOOLS
SYSTOOLS
SQL> connect / as sysdba
Connected.
SQL>
SQL> col name format a55
SQL>
SQL> select *
2 from v$result_cache_statistics
3 /
ID NAME VALUE
---------- ------------------------------------------------------- ----------
1 Block Size (Bytes) 1024
2 Block Count Maximum 1056
3 Block Count Current 32
4 Result Size Maximum (Blocks) 52
5 Create Count Success 2
6 Create Count Failure 0
7 Find Count 0
8 Invalidation Count 0
9 Delete Count Invalid 0
10 Delete Count Valid 0
SYSTOOLS
10 rows selected.
SQL>
SYSTOOLS
results that were successfully created (one for each query statement).
In the next steps, you re-execute the queries and view the cache results found.
--- query3.sql
connect oe
set echo on
SYSTOOLS
--- Cache result of both queries, then use the cached result.
. . . .
2453 04-OCT-99 06.53.34.362632 PM
direct 116 0 129 153
select /*+ result_cache q_name(Q1) */ * from orders
/ 2456 07-NOV-98 06.53.25.989889 PM
direct 117 0 3878.4 163
SYSTOOLS
CUSTOMER_ID ORD_COUNT
----------- ----------
123 1
151 1
152 1
153 1
167 1
168 1
116 4
120 1
121 1
144 5
. . . .
SYSTOOLS
SYSTOOLS
SQL> connect / as sysdba
Connected.
SQL>
SQL> col name format a55
SQL>
SQL> select *
2 from v$result_cache_statistics
3 /
ID NAME VALUE
---------- ------------------------------------------------------- ----------
1 Block Size (Bytes) 1024
2 Block Count Maximum 1056
3 Block Count Current 32
4 Result Size Maximum (Blocks) 52
5 Create Count Success 2
6 Create Count Failure 0
7 Find Count 2
8 Invalidation Count 0
9 Delete Count Invalid 0
10 Delete Count Valid 0
SYSTOOLS
10 rows selected.
SYSTOOLS
SYSTOOLS
• Improving memory usage by caching SQL result sets
– Enabling Query Result Cache
– Using the DBMS_RESULT_CACHE package
• Implementing SQL Query Result Cache
– Writing queries that use the result cache hint
• Using PL/SQL Function Result Cache
– Setting up PL/SQL functions to use PL/SQL result caching
– Implementing PL/SQL Function Result Caching
SYSTOOLS
10 - 20 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• Definition:
– Enables data that is stored in cache to be shared across
sessions
– Stores the function result cache in an SGA, making it
available to any session that runs your application
• Benefits:
– Improved performance
– Improved scalability
SYSTOOLS
10 - 21 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
the burden of designing and developing your own caches and cache-management policies.
• Scenario:SYSTOOLS
– You need a PL/SQL function that derives a complex metric.
– The data that your function calculates changes slowly, but the
function is frequently called.
• Solution:
– Use the new RESULT_CACHE clause in your function
definition.
– You can also have the cache purged when a dependent table
experiences a DML operation, by using the RELIES_ON
clause.
SYSTOOLS
10 - 22 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
values, the system returns the cached result to the caller and does not re-execute the function
body.
• If the cache does not contain the result, the system executes the function body and adds the
result (for these parameter values) to the cache before returning control to the caller.
The cache can accumulate many results—one result for every unique combination of parameter
values with which each result-cached function was called. If the system needs more memory, it ages
out (deletes) one or more cached results.
You can specify the database objects that are used to compute a cached result, so that if any of them
is updated, the cached result becomes invalid and must be recomputed.
The best candidates for result caching are functions that are called frequently but depend on
information that changes infrequently or never.
SYSTOOLS
--- flush.sql
--- Start with a clean slate. Flush the cache and shared pool.
--- Verify that memory was released.
connect / as sysdba
SET ECHO ON
SET FEEDBACK 1
SET NUMWIDTH 10
SET LINESIZE 150
SET TRIMSPOOL ON
SET TAB OFF
SET PAGESIZE 1000
SET SERVEROUTPUT ON
execute dbms_result_cache.flush
alter system flush shared_pool
/
execute dbms_result_cache.memory_report
R e s u l t C a c h e M e m o r y R e p o r t
SYSTOOLS
[Parameters]
Block Size = 1K bytes
Maximum Cache Size = 1056K bytes (1056 blocks)
Maximum Result Size = 52K bytes (52 blocks)
[Memory]
Total Memory = 5140 bytes [0.003% of the Shared Pool]
... Fixed Memory = 5140 bytes [0.003% of the Shared Pool]
... Dynamic Memory = 0 bytes [0.000% of the Shared Pool]
SYSTOOLS
SYSTOOLS
• Improving memory usage by caching SQL result sets
– Enabling Query Result Cache
– Using the DBMS_RESULT_CACHE package
• Implementing SQL Query Result Cache
– Writing queries that use the result cache hint
• Using PL/SQL Function Result Cache
– Setting up PL/SQL functions to use PL/SQL result caching
– Implementing PL/SQL Function Result Caching
SYSTOOLS
10 - 24 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
RESULT_CACHE Clause
• Include the RESULT_CACHE option in the function definition.
• Optionally, include the RELIES_ON clause.
CREATE OR REPLACE FUNCTION ORD_COUNT(cust_no number)
RETURN NUMBER
RESULT_CACHE RELIES_ON (orders)
IS
V_COUNT NUMBER;
BEGIN
SELECT COUNT(*) INTO V_COUNT
FROM orders
WHERE customer_id = cust_no;
return v_count;
SYSTOOLS
end;
SYSTOOLS
results depend
In the example shown in the slide, the ORD_COUNT function has result caching enabled through the
RESULT_CACHE option in the function declaration. In this example, the RELIES_ON clause is used
to identify the ORDERS table on which the function results depend.
You can also run DBMS_RESULT_CACHE.MEMORY_REPORT to view the result cache memory
results.
For more information about result caching in Oracle Database 11g, review the Oracle by Example
tutorial, which is available at:
http://stcontent.oracle.com/content/dav/oracle/Libraries/ST%20Curriculum/ST%20Curriculum-
Public/Courses/OBE/11gr1_db/manage/res_cache/results_cache.htm
SYSTOOLS
• Improving memory usage by caching SQL result sets
– Enabling Query Result Cache
– Using the DBMS_RESULT_CACHE package
• Implementing SQL Query Result Cache
– Writing queries that use the result cache hint
• Using PL/SQL Function Result Cache
– Setting up PL/SQL functions to use PL/SQL result caching
– Implementing PL/SQL Function Result Caching
SYSTOOLS
10 - 26 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
SQL> connect oe
Connected.
SQL> select cust_last_name, ord_count(customer_id)
no_of_orders
2 from customers
3 where cust_last_name = 'MacGraw';
CUST_LAST_NAME NO_OF_ORDERS
-------------------- ------------
MacGraw 4
1 row selected.
SYSTOOLS
10 - 27 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
SQL> SET ECHO ON
SQL> SET FEEDBACK 1
SQL> SET NUMWIDTH 10
SQL> SET LINESIZE 150
SQL> SET TRIMSPOOL ON
SQL> SET TAB OFF
SQL> SET PAGESIZE 1000
SQL>
SQL> connect / as sysdba
Connected.
SQL>
SQL> --- Establish the cache content
SQL> set serveroutput on
SQL> execute dbms_result_cache.memory_report
R e s u l t C a c h e M e m o r y R e p o r t
[Parameters]
Block Size = 1K bytes
Maximum Cache Size = 1056K bytes (1056 blocks)
Maximum Result Size = 52K bytes (52 blocks)
[Memory]
Total Memory = 103536 bytes [0.055% of the Shared Pool]
... Fixed Memory = 5140 bytes [0.003% of the Shared Pool]
... Dynamic Memory = 98396 bytes [0.052% of the Shared Pool]
SYSTOOLS
....... Overhead = 65628 bytes
....... Cache Memory = 32K bytes (32 blocks)
........... Unused Memory = 29 blocks
........... Used Memory = 3 blocks
............... Dependencies = 2 blocks (2 count)
............... Results = 1 blocks
................... PLSQL = 1 blocks (1 count)
PL/SQL procedure successfully completed.
SYSTOOLS
SQL> SYSTOOLS
SQL> connect / as sysdba
Connected.
SQL> col name format a55
SQL>
SQL> select *
2 from v$result_cache_statistics
3 /
ID NAME VALUE
---------- ------------------------ ----------
1 Block Size (Bytes) 1024
2 Block Count Maximum 1056
3 Block Count Current 32
4 Result Size Maximum (Blocks) 52
5 Create Count Success 1
6 Create Count Failure 0
7 Find Count 0
8 Invalidation Count 0
9 Delete Count Invalid 0
10 Delete Count Valid 0
SYSTOOLS
10 rows selected.
Elapsed: 00:00:05.00
SQL>
SYSTOOLS
SYSTOOLS
SQL> connect oe
Connected.
SQL> select cust_last_name, ord_count(customer_id)
no_of_orders
2 from customers
3 where cust_last_name = 'MacGraw';
CUST_LAST_NAME NO_OF_ORDERS
-------------------- ------------
MacGraw 4
1 row selected.
SYSTOOLS
10 - 30 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SQL> SYSTOOLS
SQL> connect / as sysdba
Connected.
SQL> col name format a55
SQL>
SQL> select *
2 from v$result_cache_statistics
3 /
ID NAME VALUE
---------- -------------------- ----------
1 Block Size (Bytes) 1024
2 Block Count Maximum 1056
3 Block Count Current 32
4 Result Size Maximum (Blocks) 52
5 Create Count Success 1
6 Create Count Failure 0
7 Find Count 1
8 Invalidation Count 0
9 Delete Count Invalid 0
SYSTOOLS
10 Delete Count Valid 0
10 rows selected.
Elapsed: 00:00:00.01
SQL>
SYSTOOLS
Note also that the elapsed time for the same query has reduced from 00:00:05.00 to 00:00:00.01.
SYSTOOLS
SQL> connect / as sysdba
Connected.
SQL>
SQL> col name format a55
SQL>
SQL> select type, namespace,status, scan_count,name
2 from v$result_cache_objects
3 /
TYPE NAMES STATUS SCAN_COUNT NAME
---------- ----- --------- ---------- ---------------
Dependency Published 0 OE.ORD_COUNT
Dependency Published 0 OE.ORDERS
Result PLSQL Published 1
"OE"."ORD_COUNT"::8."ORD_COUNT"#fac892c7867b54c6 #1
SYSTOOLS
3 rows selected.
SQL>
SYSTOOLS
SYSTOOLS
In this lesson, you should have learned how to:
• Improve memory usage by caching SQL result sets
• Write queries that use the result cache hint
• Use the DBMS_RESULT_CACHE package
• Set up PL/SQL functions to use PL/SQL result caching
SYSTOOLS
10 - 33 Copyright © 2008, Oracle. All rights reserved.
Summary
In this lesson, you saw the Oracle Database 11g caching techniques that can improve performance.
SYSTOOLS
SYSTOOLS
Examining SQL and PL/SQL Result Caching
This practice covers the following topics:
• Writing code to use SQL caching
• Writing code to use PL/SQL caching
SYSTOOLS
10 - 34 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
so that PL/SQL result caching is turned on.
Examining SQL and PL/SQL Result Caching
1. Use SQL Developer to connect to the OE schema. Examine the Explain Plan for this query,
which is found in the lab_10_01.sql lab file. You can see the Explain Plan by clicking the
Execute Explain Plan button on the toolbar in the Code Editor window.
SELECT count(*),
round(avg(quantity_on_hand)) AVG_AMT,
product_id, product_name
FROM inventories natural join product_information
GROUP BY product_id, product_name;
2. Add the RESULT_CACHE hint to the query and reexamine the Explain Plan results.
SELECT /*+ result_cache */
SYSTOOLS
count(*),
round(avg(quantity_on_hand)) AVG_AMT,
product_id, product_name
FROM inventories natural join product_information
GROUP BY product_id, product_name;
3. The following code is used to generate a list of warehouse names for pick lists in applications.
The WAREHOUSES table is fairly stable and is not modified often.
Click the Run Script button to compile this code (You can use the lab_10_03.sql file):
SYSTOOLS
SYSTOOLS
/
SYSTOOLS
RETURN v_wh_names;
END get_warehouse_names;
4. Because the function is called frequently, and because the content of the data returned does not
change frequently, this code is a good candidate for PL/SQL result caching.
Modify the code so that PL/SQL result caching is turned on. Click the Run Script button to
compile this code again.
SYSTOOLS
SYSTOOLS
Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Objectives
SYSTOOLS
After completing this lesson, you should be able to do the
following:
• Use the supplied packages and dictionary views to find
coding information
• Determine identifier types and usages with PL/Scope
• Use the DBMS_METADATA package to obtain metadata from
the data dictionary as XML or creation DDL that can be used
to re-create the objects
SYSTOOLS
11 - 2 Copyright © 2008, Oracle. All rights reserved.
Objectives
In this lesson, you learn how to write PL/SQL routines that analyze the PL/SQL applications.
You learn about the dictionary views and the packages that you can use to find information
within your code and to generate information about your code.
SYSTOOLS
SYSTOOLS
• Running reports on source code
• Determining identifier types and usages
• Using DBMS_METADATA to retrieve object definitions
SYSTOOLS
11 - 3 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
–
SYSTOOLS
• Use the dictionary views:
ALL_ARGUMENTS
– ALL_OBJECTS
– ALL_SOURCE
– ALL_PROCEDURES
– ALL_DEPENDENCIES
• Use the supplied packages:
– dbms_describe
– dbms_utility
SYSTOOLS
11 - 4 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
ALL_ARGUMENTS Includes information about the parameters for the procedures
and functions that you can call
ALL_PROCEDURES Contains the list of procedures and functions that you can
execute
ALL_DEPENDENCIES Is one of the several views that give you information about
the dependencies between database objects
You can also use the Oracle-supplied DBMS_DESCRIBE package to obtain information about a
PL/SQL object. The package contains the DESCRIBE_PROCEDURE procedure, which provides
a brief description of a PL/SQL stored procedure. It takes the name of a stored procedure and
returns information about each parameter of that procedure.
You can use the DBMS_UTILITY supplied package to follow a call stack and an exception
stack.
SYSTOOLS
Find all instances of CHAR in your code:
SELECT NAME, line, text
FROM user_source
WHERE INSTR (UPPER(text), ' CHAR') > 0
OR INSTR (UPPER(text), ' CHAR(') > 0
OR INSTR (UPPER(text), ' CHAR (') > 0;
SYSTOOLS
11 - 5 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
Create a package with various queries that you can easily call:
SYSTOOLS
11 - 6 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
parameter. For efficiency, the BULK COLLECT statement is used to retrieve all matching rows
into the collection variable.
The ENCAP_COMPLIANCE procedure identifies those programs that reference a table directly.
This procedure queries the ALL_DEPENDENCIES view to find the PL/SQL code objects that
directly reference a table or a view.
You can also include a procedure to validate a set of standards for exception handling.
SYSTOOLS
CREATE OR REPLACE PACKAGE BODY query_code_pkg IS
PROCEDURE find_text_in_code (str IN VARCHAR2)
IS
TYPE info_rt IS RECORD (NAME user_source.NAME%TYPE,
text user_source.text%TYPE );
TYPE info_aat IS TABLE OF info_rt INDEX BY PLS_INTEGER;
info_aa info_aat;
BEGIN
SELECT NAME || '-' || line, text
BULK COLLECT INTO info_aa FROM user_source
WHERE UPPER (text) LIKE '%' || UPPER (str) || '%'
AND NAME != 'VALSTD' AND NAME != 'ERRNUMS';
DBMS_OUTPUT.PUT_LINE ('Checking for presence of '||
str || ':');
FOR indx IN info_aa.FIRST .. info_aa.LAST LOOP
DBMS_OUTPUT.PUT_LINE (
SYSTOOLS
info_aa (indx).NAME|| ',' || info_aa (indx).text);
END LOOP;
END find_text_in_code;
PROCEDURE encap_compliance IS
SUBTYPE qualified_name_t IS VARCHAR2 (200);
TYPE refby_rt IS RECORD (NAME qualified_name_t,
referenced_by qualified_name_t );
TYPE refby_aat IS TABLE OF refby_rt INDEX BY PLS_INTEGER;
refby_aa refby_aat;
BEGIN
SELECT owner || '.' || NAME refs_table
, referenced_owner || '.' || referenced_name
AS table_referenced
BULK COLLECT INTO refby_aa
FROM all_dependencies
SYSTOOLS
WHERE owner = USER
AND TYPE IN ('PACKAGE', 'PACKAGE BODY',
'PROCEDURE', 'FUNCTION')
AND referenced_type IN ('TABLE', 'VIEW')
AND referenced_owner NOT IN ('SYS', 'SYSTEM')
ORDER BY owner, NAME, referenced_owner, referenced_name;
DBMS_OUTPUT.PUT_LINE ('Programs that reference
tables or views');
FOR indx IN refby_aa.FIRST .. refby_aa.LAST LOOP
DBMS_OUTPUT.PUT_LINE (refby_aa (indx).NAME || ',' ||
refby_aa (indx).referenced_by);
END LOOP;
END encap_compliance;
END query_code_pkg;
/
SYSTOOLS
EXECUTE query_code_pkg.encap_compliance
Programs that reference tables or views
1
OE.CREDIT_CARD_PKG,OE.CUSTOMERS
OE.LOAD_PRODUCT_IMAGE,OE.PRODUCT_INFORMATION
OE.SET_VIDEO,OE.CUSTOMERS
OE.WRITE_LOB,OE.PRODUCT_DESCRIPTIONS
...
EXECUTE query_code_pkg.find_text_in_code('customers')
2
Checking for presence of customers:
CREDIT_CARD_PKG-12, FROM customers
CREDIT_CARD_PKG-36, UPDATE customers
SYSTOOLS
CREDIT_CARD_PKG-41, UPDATE customers
SET_VIDEO-6, SELECT cust_first_name FROM customers
SET_VIDEO-13, UPDATE customers SET video = file_ptr
...
QUERY_CODE_PKG: Examples
In the first example, the ENCAP_COMPLIANCE procedure displays all PL/SQL code objects
that reference a table or view directly. Both the code name and table or view name are listed in
the output.
In the second example, the FIND_TEXT_IN_CODE procedure returns all PL/SQL code objects
SYSTOOLS
that contain the “customers” text string. The code name, line number, and line are listed in the
output.
SYSTOOLS
Use Reports:
1
SYSTOOLS
11 - 9 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
2. Expand the PL/SQL node and select the Search Source Code option.
3. Enter the connection information.
SYSTOOLS
Enter text string or
object name
Results 5
SYSTOOLS
11 - 10 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• Can be used to retrieve information about a PL/SQL object
• Contains one procedure: DESCRIBE_PROCEDURE
• Includes:
– Three scalar IN parameters
– One scalar OUT parameter
– 12 associative array OUT parameters
object_name
null
SYSTOOLS
null
describe_procedure
SYSTOOLS
The DBMS_DESCRIBE returns detailed parameter information in a set of associative arrays.
The details are numerically coded. You can find the following information from the results
returned:
• Overload: If overloaded, it holds a value for each version of the procedure.
• Position: Position of the argument in the parameter list. 0 is reserved for the RETURN
information of a function.
• Level: For composite types only; it holds the level of the data type.
• Argument name: Name of the argument.
• Data type: A numerically coded value representing a data type.
• Default value: 0 for no default value, 1 if the argument has a default value.
• Parameter mode: 0 = IN, 1 = OUT, 2 = IN OUT.
Note: This is not the complete list of values returned from the DESCRIBE_PROCEDURE
routine. For a complete list, see the PL/SQL Packages and Types Reference 11g Release 1
reference manual.
SYSTOOLS
Create a package to call the
DBMS_DESCRIBE.DESCRIBE_PROCEDURE routine:
CREATE OR REPLACE PACKAGE use_dbms_describe
1
IS
PROCEDURE get_data (p_obj_name VARCHAR2);
END use_dbms_describe;
/
EXEC use_dbms_describe.get_data('ORDERS_APP_PKG.THE_PREDICATE')
2
Name Mode Position Datatype
This is the RETURN data for the function: 1 0 1
P_SCHEMA 0 1 1
SYSTOOLS
P_NAME 0 2 1
SYSTOOLS
defined. This package holds one procedure, GET_DATA. The GET_DATA routine calls the
DBMS_DESCRIBE.DESCRIBE_PROCEDURE routine. The implementation of the
USE_DBMS_DESCRIBE package is shown on the next page. Note that several associative array
variables are defined to hold the values returned via the OUT parameters from the
DESCRIBE_PROCEDURE routine. Each of these arrays uses the predefined package types:
TYPE VARCHAR2_TABLE IS TABLE OF VARCHAR2(30)
INDEX BY BINARY_INTEGER;
TYPE NUMBER_TABLE IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
In the call to the DESCRIBE_PROCEDURE routine, you need to pass three parameters: the
name of the procedure that you are enquiring about and two null values. These null values are
reserved for future use.
In the second example in the slide, the results are displayed for the parameters of the
ORDERS_APP_PKG.THE_PREDICATE function. A data type of 1 indicates that it is a
VARCHAR2 data type.
SYSTOOLS
CREATE OR REPLACE PACKAGE use_dbms_describe IS
PROCEDURE get_data (p_obj_name VARCHAR2);
END use_dbms_describe;
/
CREATE OR REPLACE PACKAGE BODY use_dbms_describe IS
PROCEDURE get_data (p_obj_name VARCHAR2)
IS
v_overload DBMS_DESCRIBE.NUMBER_TABLE;
v_position DBMS_DESCRIBE.NUMBER_TABLE;
v_level DBMS_DESCRIBE.NUMBER_TABLE;
v_arg_name DBMS_DESCRIBE.VARCHAR2_TABLE;
v_datatype DBMS_DESCRIBE.NUMBER_TABLE;
v_def_value DBMS_DESCRIBE.NUMBER_TABLE;
v_in_out DBMS_DESCRIBE.NUMBER_TABLE;
v_length DBMS_DESCRIBE.NUMBER_TABLE;
v_precision DBMS_DESCRIBE.NUMBER_TABLE;
SYSTOOLS
v_scale DBMS_DESCRIBE.NUMBER_TABLE;
v_radix DBMS_DESCRIBE.NUMBER_TABLE;
v_spare DBMS_DESCRIBE.NUMBER_TABLE;
BEGIN
DBMS_DESCRIBE.DESCRIBE_PROCEDURE
(p_obj_name, null, null, -- these are the 3 in parameters
v_overload, v_position, v_level, v_arg_name,
v_datatype, v_def_value, v_in_out, v_length,
v_precision, v_scale, v_radix, v_spare, null);
IF v_in_out.FIRST IS NULL THEN
DBMS_OUTPUT.PUT_LINE ('No arguments to report.');
ELSE
DBMS_OUTPUT.PUT
('Name Mode');
DBMS_OUTPUT.PUT_LINE(' Position Datatype ');
FOR i IN v_arg_name.FIRST .. v_arg_name.LAST LOOP
SYSTOOLS
IF v_position(i) = 0 THEN
DBMS_OUTPUT.PUT('This is the RETURN data for
the function: ');
ELSE
DBMS_OUTPUT.PUT (
rpad(v_arg_name(i), LENGTH(v_arg_name(i)) +
42-LENGTH(v_arg_name(i)), ' '));
END IF;
DBMS_OUTPUT.PUT( ' ' ||
v_in_out(i) || ' ' || v_position(i) ||
' ' || v_datatype(i) );
DBMS_OUTPUT.NEW_LINE;
END LOOP;
END IF;
END get_data;
END use_dbms_describe;
SYSTOOLS
Query the ALL_ARGUMENTS view to find information about
arguments for procedures and functions:
SELECT object_name, argument_name, in_out, position, data_type
FROM all_arguments
WHERE package_name = 'CREDIT_CARD_PKG';
SYSTOOLS
UPDATE_CARD_INFO P_CUST_ID IN 1 NUMBER
CUST_CARD_INFO IN/OUT 1 OBJECT
CUST_CARD_INFO P_CARD_INFO IN/OUT 2 TABLE
CUST_CARD_INFO P_CUST_ID IN 1 NUMBER
CUST_CARD_INFO OUT 0 PL/SQL BOOLEAN
10 rows selected.
SYSTOOLS
and ALL_ARGUMENTS.
In the example shown in the slide, the argument name, mode, position, and data type are
returned for ORDERS_APP_PKG. Note the following:
• A position of 1 and a sequence and level of 0 indicates that the procedure has no arguments.
• For a function that has no arguments, it is displayed as a single row for the RETURN clause,
with a position of 0.
• The argument name for the RETURN clause is NULL.
• If the programs are overloaded, the OVERLOAD column (not shown in the slide) indicates
the Nth overloading; otherwise, it is NULL.
• The DATA_LEVEL column (not shown in the slide) value of 0 identifies a parameter as it
appears in the program specification.
SYSTOOLS
Other column information:
• Details about the data type are found in the DATA_TYPE and
TYPE_ columns.
• All arguments in the parameter list are at level 0.
• For composite parameters, the individual elements of the
composite are assigned levels, starting at 1.
• The POSITION-DATA_LEVEL column combination is unique
only for a level 0 argument (the actual parameter, not its
subtypes if it is a composite).
SYSTOOLS
11 - 15 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
package.
• TYPE_SUBNAME: Is relevant only for package local types. Displays the name of the type
declared in the package identified in the TYPE_NAME column. For example, if the data type
is a PL/SQL table, you can find out the type of the table only by looking at the
TYPE_SUBNAME column.
Note: The DEFAULT_VALUE and DEFAULT_LENGTH columns are reserved for future use and
do not currently contain information about a parameter’s default value. However, you can use
DBMS_DESCRIBE to find some default value information. In this package, the parameter
DEFAULT_VALUE returns 1 if there is a default value; otherwise, it returns 0.
By combining the information from DBMS_DESCRIBE and ALL_ARGUMENTS, you can find
valuable information about parameters, as well as about how your PL/SQL routines are
overloaded.
Use Reports:
SYSTOOLS 1
2 3
SYSTOOLS
11 - 16 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
2. Expand the PL/SQL node and select Program Unit Arguments. If prompted, enter the
connection information.
3. Enter the name of the program unit on which you want the arguments reported.
Results:
SYSTOOLS
4
SYSTOOLS
11 - 17 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
OUT, or IN OUT).
SYSTOOLS
• This function returns the formatted text string of the current
call stack.
• Use it to find the line of code being executed.
EXECUTE third_one
----- PL/SQL Call Stack -----
object line object
handle number name
0x566ce8e0 4 procedure OE.FIRST_ONE
0x5803f7a8 5 procedure OE.SECOND_ONE
0x569c3770 6 procedure OE.THIRD_ONE
SYSTOOLS
0x567ee3d0 1 anonymous block
SYSTOOLS
IS
BEGIN
dbms_output.put_line(
substr(dbms_utility.format_call_Stack, 1, 255));
END;
/
SYSTOOLS
CREATE OR REPLACE PROCEDURE third_one
IS
BEGIN
null;
null;
second_one;
END;
/
The output from the FORMAT_CALL_STACK function shows the object handle number, the line
number where a routine is called from, and the routine that is called. Note that the NULL;
statements added to the procedures are used to emphasize the line number where the routine is
called from.
SYSTOOLS
SYSTOOLS
SYSTOOLS
DBMS_UTILITY.FORMAT_ERROR_BACKTRACE:
• Shows you the call stack at the point where an exception is
raised
• Returns:
– The backtrace string
– A null string if no errors are being handled
Backtrace string
SYSTOOLS
Null string
Raised format_error_backtrace
exception
Using DBMS_UTILITY.FORMAT_ERROR_BACKTRACE
You can use this function to display the call stack at the point where an exception was raised,
even if the procedure is called from an exception handler in an outer scope. The output returned
is similar to the output of the SQLERRM function but not subject to the same size limitation.
Using DBMS_UTILITY.FORMAT_ERROR_STACK
SYSTOOLS
You can use this function to format the current error stack. It can be used in exception handlers
to view the full error stack. The function returns the error stack up to 2,000 bytes.
SYSTOOLS
CREATE OR REPLACE PROCEDURE top_with_logging IS
-- NOTE: SQLERRM in principle gives the same info
-- as format_error_stack.
-- But SQLERRM is subject to some length limits,
-- while format_error_stack is not.
BEGIN
P5(); -- this procedure, in turn, calls others,
-- building a stack. P0 contains the exception
EXCEPTION
WHEN OTHERS THEN
log_errors ( 'Error_Stack...' || CHR(10) ||
DBMS_UTILITY.FORMAT_ERROR_STACK() );
log_errors ( 'Error_Backtrace...' || CHR(10) ||
SYSTOOLS
DBMS_UTILITY.FORMAT_ERROR_BACKTRACE() );
DBMS_OUTPUT.PUT_LINE ( '----------' );
END top_with_logging;
/
SYSTOOLS
The LOG_ERRORS procedure is shown on the next page.
SYSTOOLS
CREATE OR REPLACE PROCEDURE log_errors ( i_buff IN VARCHAR2 ) IS
g_start_pos PLS_INTEGER := 1;
g_end_pos PLS_INTEGER;
FUNCTION output_one_line RETURN BOOLEAN IS
BEGIN
g_end_pos := INSTR ( i_buff, CHR(10), g_start_pos );
CASE g_end_pos > 0
WHEN TRUE THEN
DBMS_OUTPUT.PUT_LINE ( SUBSTR ( i_buff,
g_start_pos, g_end_pos-g_start_pos ));
g_start_pos := g_end_pos+1;
RETURN TRUE;
WHEN FALSE THEN
DBMS_OUTPUT.PUT_LINE ( SUBSTR ( i_buff, g_start_pos,
(LENGTH(i_buff)-g_start_pos)+1 ));
RETURN FALSE;
SYSTOOLS
END CASE;
END output_one_line;
BEGIN
WHILE output_one_line() LOOP NULL;
END LOOP;
END log_errors;
SYSTOOLS
FORMAT_ERROR_STACK, and the second procedure passes the results of
FORMAT_ERROR_BACKTRACE .
Note: You can use UTL_FILE instead of DBMS_OUTPUT to write and format the results to a
file.
SYSTOOLS
procedures is built. The P0 procedure raises a zero divide exception when it is invoked. The call
stack is:
TOP_WITH_LOGGING > P5 > P4 > P3 > P2 > P1 > P0
SYSTOOLS
CREATE OR REPLACE PROCEDURE P1 IS
BEGIN
P0();
END P1;
/
CREATE OR REPLACE PROCEDURE P2 IS
BEGIN
P1();
END P2;
/
CREATE OR REPLACE PROCEDURE P3 IS
BEGIN
P2();
END P3;
/
CREATE OR REPLACE PROCEDURE P4 IS
SYSTOOLS
BEGIN P3();
END P4;
/
CREATE OR REPLACE PROCEDURE P5 IS
BEGIN P4();
END P5;
/
CREATE OR REPLACE PROCEDURE top IS
BEGIN
P5(); -- this procedure is used to show the results
-- without using the TOP_WITH_LOGGING routine.
END top;
/
SET FEEDBACK ON
Results:
SYSTOOLS
EXECUTE top_with_logging
Error_Stack...
ORA-01476: divisor is equal to zero
Error_Backtrace...
ORA-06512: at "OE.P0", line 5
ORA-06512: at "OE.P1", line 3
ORA-06512: at "OE.P2", line 3
ORA-06512: at "OE.P3", line 3
ORA-06512: at "OE.P4", line 2
ORA-06512: at "OE.P5", line 2
SYSTOOLS
ORA-06512: at "OE.TOP_WITH_LOGGING", line 7
----------
SYSTOOLS
are the results:
EXECUTE top
BEGIN top; END;
*
ERROR at line 1:
ORA-01476: divisor is equal to zero
ORA-06512: at "OE.P0", line 5
ORA-06512: at "OE.P1", line 3
ORA-06512: at "OE.P2", line 3
ORA-06512: at "OE.P3", line 3
ORA-06512: at "OE.P4", line 2
ORA-06512: at "OE.P5", line 2
ORA-06512: at "OE.TOP", line 3
ORA-06512: at line 1
Note that the line number reported is misleading.
SYSTOOLS
• Running reports on source code
• Determining identifier types and usages
• Using DBMS_METADATA to retrieve object definitions
SYSTOOLS
11 - 25 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• Definition:
– Is a tool that is used for extracting, organizing, and storing
user-supplied identifiers from PL/SQL source code
– Works with the PL/SQL compiler
– Gathers data on scoping and overloading
• Benefits
– Can potentially increase developer productivity
– Is a valuable resource in helping developers understand
source code
SYSTOOLS
– Can be used to build a PL/SQL IDE
PL/Scope Concepts
With PL/Scope, you can produce a cross-referenced repository of PL/SQL identifiers to gather
information about your PL/SQL applications.
PL/Scope has two targeted audiences:
• PL/SQL application developers: Targeted to use PL/Scope through IDEs such as
SYSTOOLS
JDeveloper and SQL Developer
• IDE and Tools developers: Provides the means to build a comprehensive cross-referenced
repository by extracting, categorizing, organizing, and storing all identifiers discovered in
the PL/SQL source code
SYSTOOLS
Collected data includes:
• Identifier types
• Usages
– Declaration
– Definition
– Reference
– Call
– Assignment
• Location of usage
SYSTOOLS
11 - 27 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• Set the PL/SQL compilation parameter
PLSCOPE_SETTINGS.
• Valid values are IDENTIFIERS:
– ALL – Collect all PL/SQL identifier actions
found in compiled source
– NONE – Do not collect any identifier actions (the default)
• Set at the session, system, or per library unit basis:
– ALTER SESSION SET PLSCOPE_SETTINGS = 'IDENTIFIERS: ALL'
– ALTER SYSTEM SET PLSCOPE_SETTINGS = 'IDENTIFIERS: ALL'
– ALTER functionname COMPILE PLSCOPE_SETTINGS =
SYSTOOLS
'IDENTIFIERS: ALL'
• The USER/ALL/DBA_IDENTIFIERS catalog view holds the
collected identifier values.
Using PL/Scope
To use PL/Scope, you need to set the PL/SQL compilation parameter PLSCOPE_SETTINGS
to either 'IDENTIFIERS:ALL' or 'IDENTIFIERS:NONE'. You can use the ALTER
SESSION, ALTER SYSTEM, or ALTER COMPILE statements to set this parameter. After the
parameter is set, any code that you compile is analyzed for PL/Scope. The information collected
SYSTOOLS
is gathered in the USER/ALL/DBA_IDENTIFIERS dictionary view.
The identifier action describes how the identifier is used, such as in a declaration, definition,
reference, assignment, or call.
Query the USER|ALL|DBA_PLSQL_OBJECT_SETTINGS views to view what the
PLSCOPE_SETTINGS are set to. This view contains a column called PLSCOPE_SETTINGS.
When you query this column, by default all objects are set to 'IDENTIFIERS:NONE', unless
you reset the PL/SQL compilation parameter and recompile the code.
Column
SYSTOOLS Description
OWNER Owner of the identifier
NAME Name of the identifier (may not be unique)
SYSTOOLS
USAGE_ID The unique key for the identifier usage
LINE The line where the identifier action occurred
COL The column where the identifier action occurred
USAGE_CONTEXT_ID The context USAGE_ID of the identifier action
SYSTOOLS
SYSTOOLS
Sample data for scoping:
CREATE OR REPLACE PACKAGE BODY credit_card_pkg
IS
PROCEDURE update_card_info
(p_cust_id NUMBER, p_card_type VARCHAR2, p_card_no VARCHAR2)
IS
v_card_info typ_cr_card_nst;
i INTEGER;
BEGIN
SELECT credit_cards
...
END update_card_info;
PROCEDURE display_card_info
(p_cust_id NUMBER)
IS
SYSTOOLS
v_card_info typ_cr_card_nst;
i INTEGER;
BEGIN
SELECT credit_cards
...
END display_card_info;
END credit_card_pkg; -- package body
Sample Data
The CREDIT_CARD_PKG created earlier is used for PL/SQL scoping. The complete code is
shown on the following page.
The code is a simple package that contains one type, two procedures, and one function. Identifier
information will be collected on this package in the following pages.
SYSTOOLS
SYSTOOLS
PROCEDURE update_card_info
(p_cust_id NUMBER, p_card_type VARCHAR2, p_card_no VARCHAR2);
PROCEDURE display_card_info
(p_cust_id NUMBER);
END credit_card_pkg; -- package spec
/
SYSTOOLS
WHERE customer_id = p_cust_id;
IF v_card_info.EXISTS(1) THEN -- cards exist, add more
i := v_card_info.LAST;
v_card_info.EXTEND(1);
v_card_info(i+1) := typ_cr_card(p_card_type, p_card_no);
UPDATE customers
SET credit_cards = v_card_info
WHERE customer_id = p_cust_id;
ELSE -- no cards for this customer yet, construct one
UPDATE customers
SET credit_cards = typ_cr_card_nst
(typ_cr_card(p_card_type, p_card_no))
WHERE customer_id = p_cust_id;
END IF;
END update_card_info;
PROCEDURE display_card_info
(p_cust_id NUMBER)
IS
v_card_info typ_cr_card_nst;
SYSTOOLS
i INTEGER;
BEGIN
SELECT credit_cards
INTO v_card_info
FROM customers
WHERE customer_id = p_cust_id;
IF v_card_info.EXISTS(1) THEN
FOR idx IN v_card_info.FIRST..v_card_info.LAST LOOP
DBMS_OUTPUT.PUT('Card Type: ' || v_card_info(idx).card_type
|| ' ');
DBMS_OUTPUT.PUT_LINE('/ Card No: ' || v_card_info(idx).card_num );
END LOOP;
ELSE
DBMS_OUTPUT.PUT_LINE('Customer has no credit cards.');
END IF;
END display_card_info;
END credit_card_pkg; -- package body
/
SYSTOOLS
ALTER SESSION SET PLSCOPE_SETTINGS = 'IDENTIFIERS:ALL';
SYSTOOLS
– Describe identifier actions
Collecting Identifiers
In the example shown above, the PL/SQL compilation parameter PLSCOPE_SETTINGS is
turned on to collect information about all identifiers. The CREDIT_CARD_PKG is then
recompiled. After it is recompiled, the identifier information is available in the
ALL|USER|DBA_IDENTIFIER views.
SYSTOOLS
To verify that you have enabled identifier information to be collected on the
CREDIT_CARD_PKG package, you can issue the following statement:
SELECT PLSCOPE_SETTINGS
FROM USER_PLSQL_OBJECT_SETTINGS
WHERE NAME='CREDIT_CARD_PKG' AND TYPE='PACKAGE BODY';
PLSCOPE_SETTINGS
------------------------------
IDENTIFIERS:ALL
SYSTOOLS
Create a hierarchical report of identifier information:
WITH v AS
(SELECT Line,
Col,
INITCAP(NAME) Name,
LOWER(TYPE) Type,
LOWER(USAGE) Usage,
USAGE_ID, USAGE_CONTEXT_ID
FROM USER_IDENTIFIERS
WHERE Object_Name = 'CREDIT_CARD_PKG'
AND Object_Type = 'PACKAGE BODY' )
SELECT RPAD(LPAD(' ', 2*(Level-1)) ||
Name, 20, '.')||' '||
SYSTOOLS
RPAD(Type, 20)|| RPAD(Usage, 20)
IDENTIFIER_USAGE_CONTEXTS
FROM v
START WITH USAGE_CONTEXT_ID = 0
CONNECT BY PRIOR USAGE_ID = USAGE_CONTEXT_ID
ORDER SIBLINGS BY Line, Col;
SYSTOOLS
Results:
SYSTOOLS
IDENTIFIER_USAGE_CONTEXTS
-------------------------------------------------------------
Credit_Card_Pkg..... package definition
Cust_Card_Info.... function definition
P_Cust_Id....... formal in declaration
P_Card_Info..... formal in out declaration
V_Card_Info_Exis variable declaration
P_Card_Info..... formal in out assignment
P_Cust_Id....... formal in reference
Plitblm......... synonym call
P_Card_Info... formal in out reference
SYSTOOLS
V_Card_Info_Ex variable assignment
V_Card_Info_Exis variable assignment
...
57 rows selected.
SYSTOOLS
SYSTOOLS
Display the unique identifiers in your schema by querying for all
'DECLARATION' identifier actions:
SELECT NAME, SIGNATURE, TYPE
FROM USER_IDENTIFIERS
WHERE USAGE='DECLARATION'
ORDER BY OBJECT_TYPE, USAGE_ID;
NAME SIGNATURE TYPE
-------------------- -------------------------------- ---------------
CREDIT_CARD_PKG 66A51BCDE66BBF590EDEB7610811A453 PACKAGE
CUST_CARD_INFO D003ACE1F0208A3FF2C208F869E76C7E FUNCTION
P_CUST_ID 27A70F461EABB58444168E9628032EBD FORMAL IN
P_CARD_INFO 01BF97F7BEB616D9A0E98594DB4DABE3 FORMAL IN OUT
SYSTOOLS
UPDATE_CARD_INFO 96AE51FF4F2739AECFC92550B1799E00 PROCEDURE
P_CUST_ID 6A1CF30248AFB9EE21690B96495154F6 FORMAL IN
P_CARD_TYPE 641F9E0C76DB22D0E9674B465CFFEB48 FORMAL IN
...
I 1E6FA1EA4515EFCE69FD37307943F08D VARIABLE
IDX 4EEC75280E2FC886ECB3E76E1710C955 ITERATOR
24 rows selected.
SYSTOOLS
• TYPE: Has the value of either packages, function or procedures, object types, triggers, or
exceptions
• SIGNATURE: A unique value that distinguishes the identifier from other identifiers with
the same name, whether they are defined in the same program unit or different program
units
SYSTOOLS
VARIABLE_NAME CONTEXT_NAME SIGNATURE
------------------ ----------------- --------------------------------
V_CARD_INFO_EXISTS CUST_CARD_INFO 6B962B4BBE1B5B8C0A3EEF2A41880C21
V_CARD_INFO UPDATE_CARD_INFO 80CB5EC1F0C2CEA4171128FD462D338D
I UPDATE_CARD_INFO CE0781AFC31E0A2EC8582386F708E0F9
V_CARD_INFO DISPLAY_CARD_INFO 7EADE5CABDE4FEA1515227728D336144
I DISPLAY_CARD_INFO 1E6FA1EA4515EFCE69FD37307943F08D
SYSTOOLS
SYSTOOLS
Find all usages performed on the local variable:
SYSTOOLS
11 - 37 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
USER_IDENTIFIERS dictionary view.
The different types of the identifier usage are:
• DECLARATION
• DEFINITION
• CALL
• REFERENCE
• ASSIGNMENT
SYSTOOLS
Find out where the assignment to the local identifier i occurred:
SYSTOOLS
11 - 38 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• Running reports on source code
• Determining identifier types and usages
• Using DBMS_METADATA to retrieve object definitions
SYSTOOLS
11 - 39 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
The DBMS_METADATA package provides a centralized facility
for the extraction, manipulation, and resubmission of dictionary
metadata.
SYSTOOLS
11 - 40 Copyright © 2008, Oracle. All rights reserved.
DBMS_METADATA Package
You can invoke DBMS_METADATA to retrieve metadata from the database dictionary as XML
or creation DDL, and submit the XML to re-create the object.
You can use DBMS_METADATA for extracting metadata from the dictionary, manipulating the
metadata (adding columns, changing column data types, and so on), and then converting the
SYSTOOLS
metadata to data definition language (DDL) so that the object can be re-created on the same or
another database. In the past, you needed to do this programmatically with problems resulting in
each new release.
The DBMS_METADATA functionality is used for the Oracle 10g Export/Import replacement,
commonly called “the Data Pump.”
Note: For more information about the DBMS_DATAPUMP package, refer to the online course
titled Oracle Database 10g: Reduce Management - Tools and Utilities.
SYSTOOLS
Processing involves the following steps:
1. Fetch an object’s metadata as XML.
2. Transform the XML in a variety of ways (including
transforming it into SQL DDL).
3. Submit the XML to re-create the object.
SYSTOOLS
11 - 41 Copyright © 2008, Oracle. All rights reserved.
Metadata API
Every entity in the database is modeled as an object that belongs to an object type. For example,
the ORDERS table is an object; its object type is TABLE. When you fetch an object’s metadata,
you must specify the object type.
Every object type is implemented by using three entities:
SYSTOOLS
• A user-defined type (UDT) whose attributes comprise all metadata for objects of the type.
An object’s XML representation is a translation of a type instance into XML with the XML
tag names derived from the type attribute names. (In the case of tables, several UDTs are
needed to represent the different varieties of the object type.)
• An object view of the UDT that populates the instances of the object type
• An Extensible Style Sheet Language (XSL) script that converts the XML representation of
an object into SQL DDL
SYSTOOLS
SET_TRANSFORM_PARAM, Specifies parameters to the XSLT stylesheet identified by
SET_REMAP_PARAM transform_handle.
FETCH_XXX Returns metadata for objects that meet the criteria established by
OPEN, SET_FILTER.
CLOSE Invalidates the handle returned by OPEN and cleans up the
associated state.
Subprograms in DBMS_METADATA
The table provides an overview of the procedures and functions that are available in the
DBMS_METADATA package. To retrieve metadata, you can specify the:
• Kind of object to be retrieved—either an object type (a table, index, procedure) or a
heterogeneous collection of object types that form a logical unit (such as database export
SYSTOOLS
and schema export)
• Selection criteria (owner, name, and so on)
• “parse items” attributes of objects to be parsed and returned separately
• Transformations on the output, implemented by XSLT scripts
The package provides two types of retrieval interfaces for two types of usage:
• For programmatic use: OPEN, SET_FILTER, SET_COUNT, GET_QUERY,
SET_PARSE_ITEM, ADD_TRANSFORM, SET_TRANSFORM_PARAM,
SET_REMAP_PARAM (new in Oracle Database 10g), FETCH_xxx, and CLOSE. These
enable a flexible selection criteria and the extraction of a stream of objects.
• For use in SQL queries and for ad hoc browsing: The GET_xxx interfaces (GET_XML
and GET_DDL) return metadata for a single named object. The GET_DEPENDENT_xxx
and GET_GRANTED_xxx interfaces return metadata for one or more dependent or granted
objects. None of these APIs supports heterogeneous object types.
Name
SYSTOOLS Description
FETCH_XML This function returns the XML metadata for an object
as an XMLType.
FETCH_DDL This function returns the DDL (either to create or to
drop the object) into a predefined nested table.
FETCH_CLOB This function returns the objects (transformed or not)
as a CLOB.
FETCH_XML_CLOB This procedure returns the XML metadata for the
objects as a CLOB in an IN OUT NOCOPY parameter to
SYSTOOLS
avoid expensive LOB copies.
FETCH_xxx Subprograms
These functions and procedures return metadata for objects meeting the criteria established by
the call to the OPEN function that returned the handle, and the subsequent calls to
SET_FILTER, SET_COUNT, ADD_TRANSFORM, and so on. Each call to FETCH_xxx returns
the number of objects specified by SET_COUNT (or a smaller number, if fewer objects remain
SYSTOOLS
in the current cursor) until all objects are returned.
SYSTOOLS
• Syntax:
PROCEDURE set_filter
( handle IN NUMBER,
name IN VARCHAR2,
value IN VARCHAR2|BOOLEAN|NUMBER,
object_type_path VARCHAR2
);
• Example:
SYSTOOLS
...
DBMS_METADATA.SET_FILTER (handle, 'NAME', 'OE');
...
SET_FILTER Procedure
You use the SET_FILTER procedure to identify restrictions on the objects that are to be
retrieved. For example, you can specify restrictions on an object or schema that is being
retrieved. This procedure is overloaded with the parameters that have the following meanings:
• handle is the handle returned from the OPEN function.
SYSTOOLS
• name is the name of the filter. For each filter, the object type applies to its name, data type
(text or Boolean), and meaning or effect (including its default value, if there is one).
• value is the value of the filter. It can be text, Boolean, or a numeric value.
• object_type_path is a path name designating the object types to which the filter
applies. By default, the filter applies to the object type of the OPEN handle.
If you use an expression filter, it is placed to the right of a SQL comparison, and the value is
compared with it. The value must contain parentheses and quotation marks where appropriate. A
filter value is combined with a particular object attribute to produce a WHERE condition in the
query that fetches the objects.
SYSTOOLS
There are over 70 filters that are organized into object type
categories such as:
• Named objects
• Tables
• Objects dependent on tables
• Index
• Dependent objects
• Granted objects
• Table data
SYSTOOLS
• Index statistics
• Constraints
• All object types
• Database export
Filters
There are over 70 filters that you can specify when using the SET_FILTER procedure. These
filters are organized into object type categories. Some of the new object type categories in
Oracle Database 10g are listed in the slide.
When using the SET_FILTER procedure, you specify the name of the filter and its respective
SYSTOOLS
value.
For example, you can use the SCHEMA filter with a value to identify the schema whose objects
are selected. Then use a second call to the SET_FILTER procedure and use a filter named
INCLUDE_USER that has a Boolean data type for its value. If it is set to TRUE, objects that
contain privileged information about the user are retrieved.
DBMS_METADATA.SET_FILTER(handle, SCHEMA, 'OE');
DBMS_METADATA. SET_FILTER(handle, INCLUDE_USER, TRUE);
Each call to SET_FILTER causes a WHERE condition to be added to the underlying query that
fetches the set of objects. The WHERE conditions are combined by using an AND operator, so
that you can use multiple SET_FILTER calls to refine the set of objects to be returned.
SYSTOOLS
Set the filter to fetch the OE schema objects excluding the
object types of functions, procedures, and packages, as well as
any views that contain PAYROLL at the start of the view name:
DBMS_METADATA.SET_FILTER(handle, 'SCHEMA_EXPR',
'IN (''PAYROLL'', ''OE'')');
DBMS_METADATA.SET_FILTER(handle, 'EXCLUDE_PATH_EXPR',
'=''FUNCTION''');
DBMS_METADATA.SET_FILTER(handle, 'EXCLUDE_PATH_EXPR',
'=''PROCEDURE''');
DBMS_METADATA.SET_FILTER(handle, 'EXCLUDE_PATH_EXPR',
SYSTOOLS
'=''PACKAGE''');
DBMS_METADATA.SET_FILTER(handle, 'EXCLUDE_NAME_EXPR',
'LIKE ''PAYROLL%''', 'VIEW');
SYSTOOLS
and view object names that are to be excluded.
SYSTOOLS
CREATE PROCEDURE example_one IS
v_hdl NUMBER; v_th1 NUMBER; v_th2 NUMBER;
v_doc sys.ku$_ddls; 1
BEGIN
v_hdl := DBMS_METADATA.OPEN('SCHEMA_EXPORT'); 2
DBMS_METADATA.SET_FILTER (v_hdl,'SCHEMA','OE'); 3
v_th1 := DBMS_METADATA.ADD_TRANSFORM (v_hdl, 4
'MODIFY', NULL, 'TABLE');
DBMS_METADATA.SET_REMAP_PARAM(v_th1, 5
'REMAP_TABLESPACE', 'SYSTEM', 'TBS1');
v_th2:=DBMS_METADATA.ADD_TRANSFORM(v_hdl,'DDL');
DBMS_METADATA.SET_TRANSFORM_PARAM(v_th2,
'SQLTERMINATOR', TRUE);
DBMS_METADATA.SET_TRANSFORM_PARAM(v_th2, 6
'REF_CONSTRAINTS', FALSE, 'TABLE');
SYSTOOLS
LOOP
v_doc := DBMS_METADATA.FETCH_DDL(v_hdl); 7
EXIT WHEN v_doc IS NULL;
END LOOP;
DBMS_METADATA.CLOSE(v_hdl); 8
END;
SYSTOOLS
holds the CLOB type of data.
2. You use the OPEN function to specify the type of object to be retrieved, the version of its
metadata, and the object model. It returns a context handle for the set of objects.
In this example, 'SCHEMA_EXPORT' is the object type, which indicates all metadata
objects in a schema. There are 85 predefined types of objects for the model that you can
specify for this parameter. Both the version of metadata and the object model parameters
are not identified in this example. The version of metadata parameter defaults to
'COMPATIBLE'. You can also specify 'LATEST' or a specific database version.
3. The SET_FILTER procedure identifies restrictions on the objects that are to be retrieved.
SYSTOOLS
XML representation of the retrieved objects. You can have multiple transforms. In the
example, two transforms occur, one for each of the th1 and th2 program variables. The
ADD_TRANSFORM function accepts four parameters and returns a number representing the
opaque handle to the transform. The parameters are the handle returned from the OPEN
statement, the name of the transform (DDL, DROP, or MODIFY), the encoding name (which
is the name of the national language support [NLS] character set in which the style sheet
pointed to by the name is encoded), and the object type. If the object type is omitted, the
transform applies to all objects; otherwise, it applies only to the object type specified.
The first transform shown in the program code is the handle returned from the OPEN
function. The second transform shown in the code has two parameter values specified. The
first parameter is the handle identified from the OPEN function. The second parameter value
is the DDL, which means the document is transformed to the DDL that creates the object.
The output of this transform is not an XML document. The third and fourth parameters are
not specified. Both take the default values for the encoding and object type parameters.
5. The SET_REMAP_PARAM procedure identifies the parameters to the XSLT style sheet
SYSTOOLS
identified by the transform handle, which is the first parameter passed to the procedure. In
the example, the second parameter value 'REMAP_TABLESPACE' means that the objects
have their tablespaces renamed from an old value to a new value. In the ADD_TRANSFORM
function, the choices are DDL, DROP, or MODIFY. For each of these values, the
SET_REMAP_PARAM identifies the name of the parameter. REMAP_TABLESPACE means
the objects in the document will have their tablespaces renamed from an old value to a new
value. The third and fourth parameters identify the old value and new value. In this
example, the old tablespace name is SYSTEM, and the new tablespace name is TBS1.
6. SET_TRANSFORM_PARAM works similarly to SET_REMAP_PARAM. In the code shown,
the first call to SET_TRANSFORM_PARAM identifies the parameters for the th2 variable.
The SQLTERMINATOR and TRUE parameter values cause the SQL terminator (; or /) to
be appended to each DDL statement.
The second call to SET_TRANSFORM_PARAM identifies more characteristics for the th2
variable. REF_CONSTRAINTS, FALSE, and TABLE means that the referential constraints
on the tables are not copied to the document.
SYSTOOLS
7. The FETCH_DDL function returns the metadata for objects that meet the criteria established
by the OPEN, SET_FILTER, ADD_TRANSFORM, SET_REMAP_PARAM, and
SET_TRANSFORM_PARAM subroutines.
8. The CLOSE function invalidates the handle returned by the OPEN function and cleans up
the associated state. Use this function to terminate the stream of objects established by the
OPEN function.
SYSTOOLS
CREATE FUNCTION get_table_md RETURN CLOB IS
v_hdl NUMBER; -- returned by 'OPEN'
v_th NUMBER; -- returned by 'ADD_TRANSFORM'
v_doc CLOB;
BEGIN
-- specify the OBJECT TYPE
v_hdl := DBMS_METADATA.OPEN('TABLE');
-- use FILTERS to specify the objects desired
DBMS_METADATA.SET_FILTER(v_hdl ,'SCHEMA','OE');
DBMS_METADATA.SET_FILTER
(v_hdl ,'NAME','ORDERS');
-- request to be TRANSFORMED into creation DDL
v_th := DBMS_METADATA.ADD_TRANSFORM(v_hdl,'DDL');
-- FETCH the object
SYSTOOLS
v_doc := DBMS_METADATA.FETCH_CLOB(v_hdl);
-- release resources
DBMS_METADATA.CLOSE(v_hdl);
RETURN v_doc;
END;
/
SYSTOOLS
CREATE TABLE "OE"."ORDERS"
( "ORDER_ID" NUMBER(12,0),
"ORDER_DATE" TIMESTAMP (6) WITH LOCAL TIME ZONE
CONSTRAINT "ORDER_DATE_NN" NOT
NULL ENABLE,
"ORDER_MODE" VARCHAR2(8),
"CUSTOMER_ID" NUMBER(6,0) CONSTRAINT
"ORDER_CUSTOMER_ID_NN" NOT NULL ENABLE,
"ORDER_STATUS" NUMBER(2,0),
"ORDER_TOTAL" NUMBER(8,2),
"SALES_REP_ID" NUMBER(6,0),
"PROMOTION_ID" NUMBER(6,0),
CONSTRAINT "ORDER_MODE_LOV" CHECK (order_mode in
...
SYSTOOLS
CONSTRAINT "ORDER_TOTAL_MIN" CHECK (order_total >= 0) ENABLE,
CONSTRAINT "ORDER_PK" PRIMARY KEY ("ORDER_ID")
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOLOGGING
COMPUTE STATISTICS
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS
2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL
DEFAULT)
TABLESPACE "EXAMPLE" ENABLE,
CONSTRAINT "ORDERS_CUSTOMER_ID_FK" FOREIGN KEY
("CUSTOMER_ID")
REFERENCES "OE"."CUSTOMERS" ("CUSTOMER_ID")
ON DELETE SET NULL ENABLE,
SYSTOOLS
CONSTRAINT "ORDERS_SALES_REP_FK" FOREIGN KEY
("SALES_REP_ID") REFERENCES "HR"."EMPLOYEES"
("EMPLOYEE_ID") ON DELETE SET NULL ENABLE
)
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
NOCOMPRESS NOLOGGING
STORAGE(INITIAL 65536 NEXT 1048576
MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT)
TABLESPACE "EXAMPLE"
You can accomplish the same effect with the browsing interface:
SELECT dbms_metadata.get_ddl
SYSTOOLS
('TABLE','ORDERS','OE')
FROM dual;
SYSTOOLS
Name Description
GET_XXX The GET_XML and GET_DDL functions return
metadata for a single named object.
GET_DEPENDENT_XXX This function returns metadata for a dependent
object.
GET_GRANTED_XXX This function returns metadata for a granted
object.
SYSTOOLS
11 - 51 Copyright © 2008, Oracle. All rights reserved.
Browsing APIs
The browsing APIs are designed for use in SQL queries and ad hoc browsing. These functions
allow you to fetch metadata for objects with a single call. They encapsulate calls to OPEN,
SET_FILTER, and so on. The function that you use depends on the characteristics of the object
type and whether you want XML or DDL.
SYSTOOLS
For some object types, you can use multiple functions. You can use GET_XXX to fetch an index
by name, or GET_DEPENDENT_XXX to fetch the same index by specifying the table on which
it is defined.
GET_XXX returns a single object name.
For GET_DEPENDENT_XXX and GET_GRANTED_XXX, an arbitrary number of granted or
dependent objects may match the input criteria. However, you can specify an object count when
fetching these objects.
If you invoke these functions from SQL*Plus, you should use the SET LONG and SET
PAGESIZE commands to retrieve the complete, uninterrupted output.
SET LONG 2000000
SET PAGESIZE 300
SYSTOOLS
1. Get the XML representation of OE.ORDERS:
SELECT DBMS_METADATA.GET_XML
('TABLE', 'ORDERS', 'OE')
FROM dual;
SYSTOOLS
('SYSTEM_GRANT', 'OE')
FROM dual;
SYSTOOLS
<ROW>
<TABLE_T>
<VERS_MAJOR>1</VERS_MAJOR>
2. Results for fetching the DDL for all object grants on OE.ORDERS:
DBMS_METADATA.GET_DEPENDENT_DDL
('OBJECT_GRANT','ORDERS','OE')
------------------------------------------------
GRANT SELECT ON "OE"."ORDERS" TO "PM"
GRANT SELECT ON "OE"."ORDERS" TO "BI"
3. Results for fetching the DDL for all system grants granted to OE:
DBMS_METADATA.GET_GRANTED_DDL('SYSTEM_GRANT','OE')
-------------------------------------------------------
GRANT QUERY REWRITE TO "OE"
...
BEGIN
SYSTOOLS
DBMS_METADATA.SET_TRANSFORM_PARAM(
DBMS_METADATA.SESSION_TRANSFORM, 1
'STORAGE', false);
END;
/
SELECT DBMS_METADATA.GET_DDL('TABLE',u.table_name)
FROM user_all_tables u 2
WHERE u.nested = 'NO'
AND (u.iot_type IS NULL OR u.iot_type = 'IOT');
SYSTOOLS
BEGIN
DBMS_METADATA.SET_TRANSFORM_PARAM( 3
DBMS_METADATA.SESSION_TRANSFORM, 'DEFAULT');
END;
/
SYSTOOLS
returned in the SQL DDL. The SESSION_TRANSFORM function is interpreted to mean
“for the current session.”
2. Use the GET_DDL function to retrieve DDL on all nonnested and non-IOT (index-
organized table) tables.
CREATE TABLE "HR"."COUNTRIES"
( "COUNTRY_ID" CHAR(2)
CONSTRAINT "COUNTRY_ID_NN" NOT NULL ENABLE,
"COUNTRY_NAME" VARCHAR2(40),
"REGION_ID" NUMBER,
CONSTRAINT "COUNTRY_C_ID_PK"
PRIMARY KEY ("COUNTRY_ID") ENABLE,
CONSTRAINT "COUNTR_REG_FK" FOREIGN KEY
...
3. Reset the session-level parameters to their defaults.
SYSTOOLS
In this lesson, you should have learned how to:
• Use the supplied packages and the dictionary views to find
coding information
• Determine identifier types and usages with PL/Scope
• Use the DBMS_METADATA package to obtain metadata from
the data dictionary as XML or creation DDL that can be used
to re-create the objects
SYSTOOLS
11 - 54 Copyright © 2008, Oracle. All rights reserved.
Summary
In this lesson, you learned how to use the dictionary views and supplied PL/SQL packages to
analyze your PL/SQL applications.
Use the OE schema for this practice.
For detailed instructions about performing this practice, see Appendix A, “Practice Solutions.”
SYSTOOLS
SYSTOOLS
This practice covers the following topics:
• Analyzing PL/SQL code
• Using PL/Scope
• Using DBMS_METADATA
SYSTOOLS
11 - 55 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
• Use DBMS_METADATA
For detailed instructions about performing this practice, see Appendix A, “Practice Solutions.”
SYSTOOLS
In this practice, you use PL/SQL and SQL Developer to analyze your code.
1. Create the QUERY_CODE_PKG package to search your source code.
a. Run the lab_11_01_a.sql script to create the QUERY_CODE_PKG package.
b. Run the ENCAP_COMPLIANCE procedure to see which of your programs reference
tables or views. (Note: Your results might differ slightly.)
c. Run the FIND_TEXT_IN_CODE procedure to find all references to ‘ORDERS.’
(Note: Your results might differ slightly.)
d. Use the SQL Developer Reports feature to find the same results for step C shown
above.
SYSTOOLS
SYSTOOLS
SYSTOOLS
2. In this practice, you use PL/Scope.
a. Enable your session to collect identifiers.
ALTER SESSION SET PLSCOPE_SETTINGS = 'IDENTIFIERS:ALL';
b. Recompile your CREDIT_CARD_PKG code.
ALTER PACKAGE credit_card_pkg COMPILE;
c. Verify that your PLSCOPE_SETTING is set correctly by issuing the following
statement:
SELECT PLSCOPE_SETTINGS
FROM USER_PLSQL_OBJECT_SETTINGS
WHERE NAME='CREDIT_CARD_PKG' AND TYPE='PACKAGE BODY';
d. Execute the following statement to create a hierarchical report on the identifier
information about the CREDIT_CARD_PKG code. You can run the
lab_11_02_d.sql script file.
WITH v AS
(SELECT Line,
SYSTOOLS
Col,
INITCAP(NAME) Name,
LOWER(TYPE) Type,
LOWER(USAGE) Usage,
USAGE_ID, USAGE_CONTEXT_ID
FROM USER_IDENTIFIERS
WHERE Object_Name = 'CREDIT_CARD_PKG'
AND Object_Type = 'PACKAGE BODY' )
SELECT RPAD(LPAD(' ', 2*(Level-1)) ||
Name, 20, '.')||' '||
RPAD(Type, 20)|| RPAD(Usage, 20)
IDENTIFIER_USAGE_CONTEXTS
FROM v
START WITH USAGE_CONTEXT_ID = 0
CONNECT BY PRIOR USAGE_ID = USAGE_CONTEXT_ID
ORDER SIBLINGS BY Line, Col;
SYSTOOLS
SYSTOOLS
3. Use DBMS_METADATA to find the metadata for the ORDER_ITEMS table.
a. Create the GET_TABLE_MD function. You can run the lab_11_03_a.sql script.
CREATE FUNCTION get_table_md RETURN CLOB IS
v_hdl NUMBER; -- returned by 'OPEN'
v_th NUMBER; -- returned by 'ADD_TRANSFORM'
v_doc CLOB;
BEGIN
-- specify the OBJECT TYPE
v_hdl := DBMS_METADATA.OPEN('TABLE');
-- use FILTERS to specify the objects desired
DBMS_METADATA.SET_FILTER(v_hdl ,'SCHEMA','OE');
DBMS_METADATA.SET_FILTER
(v_hdl ,'NAME','ORDER_ITEMS');
-- request to be TRANSFORMED into creation DDL
v_th := DBMS_METADATA.ADD_TRANSFORM(v_hdl,'DDL');
-- FETCH the object
SYSTOOLS
v_doc := DBMS_METADATA.FETCH_CLOB(v_hdl);
-- release resources
DBMS_METADATA.CLOSE(v_hdl);
RETURN v_doc;
END;
/
b. Issue the following statements to view the metadata generated from the
GET_TABLE_MD function:
set pagesize 0
set long 1000000
SYSTOOLS
DBMS_METADATA.GET_XML function. Spool the output to a file named
ORDER_ITEMS_XML.txt in the D:\Labs folder.
SYSTOOLS
Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Objectives
SYSTOOLS
After completing this lesson, you should be able to do the
following:
• Trace PL/SQL program execution
• Profile PL/SQL applications
SYSTOOLS
12 - 2 Copyright © 2008, Oracle. All rights reserved.
Objectives
In this lesson, you learn how to write PL/SQL routines that analyze the PL/SQL applications.
You are introduced to tracing PL/SQL code and profiling PL/SQL code.
SYSTOOLS
SYSTOOLS
• Tracing PL/SQL program execution
• Profiling PL/SQL applications
SYSTOOLS
12 - 3 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
Tracing PL/SQL execution provides you with a better
understanding of the program execution path, and is possible
by using the dbms_trace package.
SYSTOOLS
API for tracing the execution of PL/SQL programs on the server. You can use the Trace API,
implemented on the server as the dbms_trace package, to trace PL/SQL subprogram code.
Note: You cannot use PL/SQL tracing with the multithreaded server (MTS).
SYSTOOLS
The dbms_trace package contains:
• set_plsql_trace (trace_level INTEGER)
• clear_plsql_trace
• plsql_trace_version
SYSTOOLS
12 - 5 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
the trace level at which you want your PL/SQL code
traced as an IN parameter.)
clear_plsql_trace Stops trace data dumping in a session
plsql_trace_version Returns the version number of the trace package as an
OUT parameter
A typical trace session involves:
• Enabling specific subprograms for trace data collection (optional)
• Starting the PL/SQL tracing session (dbms_trace.set_plsql_trace)
• Running the application that is to be traced
• Stopping the PL/SQL tracing session (dbms_trace.clear_plsql_trace)
SYSTOOLS
• Using set_plsql_trace, select a trace level to identify
how to trace calls, exceptions, SQL, and lines of code.
• Trace-level constants:
– trace_all_calls – trace_all_lines
– trace_enabled_calls – trace_stop
– trace_all_sql – trace_pause
– trace_enabled_sql – trace_resume
– trace_all_exceptions
– trace_enabled_exceptions
SYSTOOLS
– trace_enabled_lines
SYSTOOLS
• Level 2: Trace calls only to enabled program units. This corresponds to the constant
trace_enabled_calls.
Trace Exceptions
• Level 1: Trace all exceptions. This corresponds to trace_all_exceptions.
• Level 2: Trace exceptions raised only in enabled program units. This corresponds to
trace_enabled_exceptions.
Trace SQL
• Level 1: Trace all SQL. This corresponds to the constant trace_all_sql.
• Level 2: Trace SQL in only enabled program units. This corresponds to the constant
trace_enabled_sql.
Trace Lines
• Level 1: Trace all lines. This corresponds to the constant trace_all_lines.
• Level 2: Trace lines only in enabled program units. This corresponds to the constant
trace_enabled_lines.
Oracle Database 11g: Advanced PL/SQL 12 - 6
Tracing PL/SQL: Steps
1
SYSTOOLS 2 3
5 4
SYSTOOLS
Read and interpret the
trace information.
Use dbms_trace.
clear_plsql_trace
to stop tracing data.
SYSTOOLS
4. Use dbms_trace.clear_plsql_trace to stop tracing data.
5. Read and interpret the trace information.
The next few pages demonstrate the steps to accomplish PL/SQL tracing.
SYSTOOLS
Enable specific subprograms with one of the two methods:
• Enable a subprogram by compiling it with the debug option:
ALTER SESSION SET PLSQL_DEBUG=true;
SYSTOOLS
12 - 8 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
• Enable a subprogram by compiling it with the ALTER SESSION debug option, and then
compile the program unit by using the CREATE OR REPLACE syntax:
ALTER SESSION SET PLSQL_DEBUG = true;
CREATE OR REPLACE ...
• Recompile a specific subprogram with the debug option:
ALTER [PROCEDURE | FUNCTION | PACKAGE]
<subprogram-name> COMPILE DEBUG [BODY];
ALTER PROCEDURE P5 COMPILE DEBUG;
Note: The second method cannot be used for anonymous blocks.
Enabling specific subprograms enables you to:
• Limit and control the amount of trace data, especially in large applications.
• Obtain additional trace information that is otherwise not available. For example, during the
tracing session, if a subprogram calls another subprogram, the name of the called
subprogram is included in the trace data if the calling subprogram was enabled by
compiling it in debug mode.
Oracle Database 11g: Advanced PL/SQL 12 - 8
Steps 2 and 3: Identify a Trace Level and Start
SYSTOOLS Tracing
• Specify the trace level by using
dbms_trace.set_plsql_trace:
EXECUTE DBMS_TRACE.SET_PLSQL_TRACE -
(tracelevel1 + tracelevel2 ...)
SYSTOOLS
12 - 9 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
• Execute the PL/SQL code. The trace data is written to the data dictionary views.
Note: To specify additional trace levels in the argument, use the “+” symbol between each trace
level value.
SYSTOOLS
Remember to turn tracing off by using the
dbms_trace.clear_plsql_trace procedure.
EXECUTE DBMS_TRACE.CLEAR_PLSQL_TRACE
SYSTOOLS
12 - 10 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
Examine the trace information:
• Call tracing writes out the program unit type, name, and
stack depth.
• Exception tracing writes out the line number.
SYSTOOLS
12 - 11 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
• If the current subprogram is enabled, call tracing writes out the subprogram type, name, and
stack depth.
• If the current subprogram is not enabled, call tracing writes out the subprogram type, line
number, and stack depth.
• Exception tracing writes out the line number. Raising the exception shows information
about whether the exception is user-defined or predefined and, in the case of predefined
exceptions, the exception number.
Note: An enabled subprogram is compiled with the debug option.
SYSTOOLS
• Trace information is written to the following dictionary views:
– plsql_trace_runs dictionary view
– plsql_trace_events dictionary view
• Run the tracetab.sql script to create the
dictionary views.
• You need privileges to view the trace information in the
dictionary views.
SYSTOOLS
12 - 12 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
script as SYS. After the script is run, you need the SELECT privilege to view information from
these dictionary views.
CONNECT /as sysdba
@D:\app\Administrator\product\11.1.0\db_1\RDBMS\ADMIN
\tracetab
GRANT SELECT ON plsql_trace_runs TO OE;
GRANT SELECT ON plsql_trace_events TO OE;
CONNECT oe
SYSTOOLS
ALTER SESSION SET PLSQL_DEBUG=TRUE;
ALTER PROCEDURE P5 COMPILE DEBUG;
EXECUTE DBMS_TRACE.SET_PLSQL_TRACE(DBMS_TRACE.trace_all_calls)
EXECUTE p5
EXECUTE DBMS_TRACE.CLEAR_PLSQL_TRACE
SYSTOOLS
PROC_NAME PROC_LINE EVENT_PROC_NAME EVENT_COMMENT
---------- ---------- ---------------- ---------------
P5 1 Procedure Call
P4 1 P5 Procedure Call
2 rows selected.
SYSTOOLS
subprograms.
SYSTOOLS
• Tracing PL/SQL program execution
• Profiling PL/SQL applications
SYSTOOLS
12 - 14 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• Definition:
– Used to identify hotspots and performance tuning
opportunities in PL/SQL applications
– Reports the dynamic execution profile of a PL/SQL program
organized by function calls
– Reports SQL and PL/SQL execution times separately
– Provides function level summaries
• Benefits:
– Provides more information than a flat profiler
SYSTOOLS
– Can be used to understand the structure and control flow of
complex programs
SYSTOOLS
You can view function level summaries that include:
• Number of calls to a function
• Time spent in the function itself
• Time spent in the entire subtree under the function
• Detailed parent-children information for each function
You can use this information to tune your PL/SQL applications, and understand the structure,
flow, and control of complex programs (especially those written by someone else).
SYSTOOLS
The PL/SQL hierarchical profiler consists of the:
• Data collection component
• Analyzer component
SYSTOOLS
12 - 16 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
• The analyzer component, which is also exposed by the DBMS_HPROF package, is used to
process the raw profiler output and upload the results of the profiling into database tables
that can then be queried. You can use the plshprof command-line utility to generate
simple HTML reports directly from the raw profiler data.
SYSTOOLS
By using the PL/SQL profiler, you can find:
• The number of calls to a function
• The function time, not including descendants
• The subtree time, including descendants
• Parent-children information for each function
– Who were the callers of a given function?
– What functions were called from a particular function?
– How much time was spent in function X when called from
function Y?
SYSTOOLS
– How many calls to function X came from function Y?
– How many times did X call Y?
SYSTOOLS
You do not need to recompile PL/SQL modules to use the hierarchical profiler. You can analyze
both interpreted and natively compiled PL/SQL modules.
SYSTOOLS
Sample data for profiling:
CREATE OR REPLACE PACKAGE BODY credit_card_pkg
IS
PROCEDURE update_card_info
(p_cust_id NUMBER, p_card_type VARCHAR2, p_card_no VARCHAR2)
IS
v_card_info typ_cr_card_nst;
i INTEGER;
BEGIN
SELECT credit_cards
...
END update_card_info;
PROCEDURE display_card_info
(p_cust_id NUMBER)
IS
SYSTOOLS
v_card_info typ_cr_card_nst;
i INTEGER;
BEGIN
SELECT credit_cards
...
END display_card_info;
END credit_card_pkg; -- package body
Sample Data
The CREDIT_CARD_PKG that was created earlier is used to demonstrate hierarchical profiling.
The full code is shown on the following page.
SYSTOOLS
SYSTOOLS
PROCEDURE update_card_info
(p_cust_id NUMBER, p_card_type VARCHAR2, p_card_no VARCHAR2);
PROCEDURE display_card_info
(p_cust_id NUMBER);
END credit_card_pkg; -- package spec
/
SYSTOOLS
WHERE customer_id = p_cust_id;
IF v_card_info.EXISTS(1) THEN -- cards exist, add more
i := v_card_info.LAST;
v_card_info.EXTEND(1);
v_card_info(i+1) := typ_cr_card(p_card_type, p_card_no);
UPDATE customers
SET credit_cards = v_card_info
WHERE customer_id = p_cust_id;
ELSE -- no cards for this customer yet, construct one
UPDATE customers
SET credit_cards = typ_cr_card_nst
(typ_cr_card(p_card_type, p_card_no))
WHERE customer_id = p_cust_id;
END IF;
END update_card_info;
PROCEDURE display_card_info
(p_cust_id NUMBER)
IS
v_card_info typ_cr_card_nst;
SYSTOOLS
i INTEGER;
BEGIN
SELECT credit_cards
INTO v_card_info
FROM customers
WHERE customer_id = p_cust_id;
IF v_card_info.EXISTS(1) THEN
FOR idx IN v_card_info.FIRST..v_card_info.LAST LOOP
DBMS_OUTPUT.PUT('Card Type: ' || v_card_info(idx).card_type
|| ' ');
DBMS_OUTPUT.PUT_LINE('/ Card No: ' || v_card_info(idx).card_num );
END LOOP;
ELSE
DBMS_OUTPUT.PUT_LINE('Customer has no credit cards.');
END IF;
END display_card_info;
END credit_card_pkg; -- package body
/
SYSTOOLS
BEGIN
-- start profiling 1
DBMS_HPROF.START_PROFILING('PROFILE_DATA', 'pd_cc_pkg.txt');
END;
DECLARE
v_card_info typ_cr_card_nst; 2
BEGIN
-- run application
credit_card_pkg.update_card_info
(154, 'Discover', '123456789');
SYSTOOLS
END;
BEGIN
DBMS_HPROF.STOP_PROFILING; 3
END;
SYSTOOLS
identify this information:
CREATE DIRECTORY profile_data AS 'D:\labs\labs';
1. The first step is to turn profiling on. Use the DBMS_HPROF.START_PROFILING
procedure. When calling this procedure, pass these two parameters:
- Directory object: An alias for a file system path name. You need to have WRITE
privileges to this location.
- File name: The name of the file to which you want the output written.
- You can optionally pass a third parameter, max_depth. When max_depth value is
NULL (the default), profile information is gathered for all functions irrespective of
their call depth. When a non-NULL value is specified, the profiler collects data only
for functions up to a call depth level of max_depth.
2. The second step is to run the code that you want profiled.
3. The third step is to turn off profiling. Use the DBMS_HPROF.STOP_PROFILING
procedure to stop the profiling.
EXECUTE DBMS_HPROF.STOP_PROFILING
Oracle Database 11g: Advanced PL/SQL 12 - 20
Understanding Raw Profiler Data
P#!
P#C
P#X
SYSTOOLS
PL/SQL Timer Started
PLSQL."".""."__plsql_vm"
3
P#C PLSQL."".""."__anonymous_block"
P#X 1634
P#C PLSQL."OE"."CREDIT_CARD_PKG"::11."UPDATE_CARD_INFO"#71749359b90ac246
#24
P#X 7
P#C PLSQL."OE"."CREDIT_CARD_PKG"::11."CUST_CARD_INFO"#c2ad85321cb9b0ae
#4
P#X 11
P#C SQL."OE"."CREDIT_CARD_PKG"::11."__static_sql_exec_line10" #10
P#X 1502
P#R
...
P#C PLSQL."".""."__plsql_vm"
SYSTOOLS
P#X 3
P#C PLSQL."".""."__anonymous_block"
P#X 15
P#C PLSQL."SYS"."DBMS_HPROF"::11."STOP_PROFILING"#980980e97e42f8ec #53
P#R
P#R
P#! PL/SQL Timer Stopped
SYSTOOLS
• P#V – PLSHPROF banner with version number
• P#C – Call to a subprogram (call event)
• P#R – Return from a subprogram (call event)
• P#X – Elapsed time between preceding and following events
• P#! – Comment
As you will see next, the DBMS_HPROF.ANALYZE function generates easier-to-decipher data
and saves the data in tables.
SYSTOOLS
• Upload the raw profiler data into the database tables.
• Run the dbmshptab.sql script that is located in the
/home/rdbms/admin folder to set up the profiler tables.
CONNECT OE
-- run this only once per schema
-- under the schema where you want the profiler tables located
@D:\app\Administrator\product\11.1.0\db_1\RDBMS\ADMIN\dbmshptab.sql
SYSTOOLS
DBMSHP_RUNS Contains top-level information for each run command
DBMSHP_FUNCTION_INFO Contains information on each function profiled
SYSTOOLS
The script creates three tables and other data structures that are required for persistently storing
the profiler data.
Note: Running the script a second time drops any previously created hierarchical profiler tables.
SYSTOOLS
DBMS_HPROF.ANALYZE:
• Analyzes the raw profiler data
• Generates hierarchical profiler information in the profiler
database tables
• Definition:
DBMS_HPROF.ANALYZE(
location IN VARCHAR2,
filename IN VARCHAR2,
summary_mode IN BOOLEAN DEFAULT FALSE,
trace IN VARCHAR2 DEFAULT NULL,
SYSTOOLS
skip IN PLS_INTEGER DEFAULT 0,
collect IN PLS_INTEGER DEFAULT NULL,
run_comment IN VARCHAR2 DEFAULT NULL)
RETURN NUMBER;
SYSTOOLS
• Filename: The file name of the raw profiler data to be analyzed.
• summary_mode: A Boolean that identifies whether to generate only top-level summary
information into the database tables (TRUE) or to provide detailed analysis (FALSE). The
default is false.
• Trace: Identifies whether to analyze only the subtrees rooted at the specified trace entry or
perform the analysis for the entire run. This parameter is specified in a special, qualified
format within quotation marks. It includes the schema name, module name, and function
name. For example "SCOTT"." "PKG"."FOO".
• Skip: Analyzes only the subtrees rooted at the specified trace, but ignores the first “skip”
invocations to trace. The default value for “skip” is 0. Used only when trace is specified.
• Collect: Analyzes “collect” member of invocations of traces (starting from “skip” + 1). By
default, only one invocation is collected. Used only when trace is specified.
• run_comment: A comment for your run.
SYSTOOLS
Hierarchical Profiler Tables
• Use the DBMS_HPROF.ANALYZE function to upload the raw
profiler results into the database tables.
DECLARE
v_runid NUMBER;
BEGIN
v_runid := DBMS_HPROF.ANALYZE (LOCATION => 'PROFILE_DATA',
FILENAME => 'pd_cc_pkg.txt');
DBMS_OUTPUT.PUT_LINE('Run ID: ' || v_runid);
END;
• This function returns a unique run identifier for the run. You
can use this identifier to look up results corresponding to this
RUN_ID
--------
1
SYSTOOLS
run from the hierarchical profiler tables.
SYSTOOLS
SYSTOOLS
12 - 25 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
DBMS_HPROF.ANALYZE is run. This table contains top-level information for each run of the
DBMS_HPROF.ANALYZE command. From the output, you can see the run ID, the timestamp of
the run, and the total elapsed time in milliseconds. If you provided a comment for the run, you
can retrieve that information from the RUN_COMMENT column (not shown).
SYSTOOLS
DBMSHP_FUNCTION_INFO Table
Query the DBMSHP_FUNCTION_INFO table to find information
about each function profiled:
SELECT owner, module, type, function line#, namespace,
calls, function_elapsed_time
FROM dbmshp_function_info
WHERE runid = 1;
SYSTOOLS
OE CREDIT_CARD PACKAGE BODY UPDATE_CARD_INFO PLSQL 1 38
_PKG
SYS DBMS_HPROF PACKAGE BODY STOP_PROFILING PLSQL 1 0
_PKG
OE CREDIT_CARD PACKAGE BODY _static_sql_exec_line10 SQL 1 1502
_PKG
OE CREDIT_CARD PACKAGE BODY _static_sql_exec_line41 SQL 1 8999
_PKG
SYSTOOLS
• MODULE: The module name
• TYPE: Module type, such as package, package body, procedure, and so on
• LINE#: The line number in the module at which the function is defined. This line# helps
identify the source location of the function in the module and can be used by the integrated
development environment (IDE) tools to navigate to the appropriate location in the source
where the function is defined. The line number can also be used to distinguish between
overloaded routines.
• NAMESPACE: The language information. At this point in time, SQL and PL/SQL are
supported.
• CALLS: The number of calls to the function
• FUNCTION_ELAPSED_TIME: The time in microseconds, not including the time spent in
descendant functions
SYSTOOLS
• plshprof is a command-line utility.
• You can use it to generate simple HTML reports directly from
the raw profiler data.
• The HTML reports can be browsed in any browser.
• The navigational capabilities combined with the links provide
a means for you to analyze the performance of large
applications.
SYSTOOLS
12 - 27 Copyright © 2008, Oracle. All rights reserved.
Introducing plshprof
plshprof is a command-line utility that you can use to generate HTML reports based on the
raw profiler data generated by the data collection component after running the
DBMS_HPROF.ANALYZE PL/SQL API.
SYSTOOLS
SYSTOOLS
After generating the raw profiler output file:
1. Change to the directory where you want the HTML output
placed.
2. Run plshprof.
– Syntax:
plshprof [option…] output_filename_1 output_filename_2
– Example:
SYSTOOLS
12 - 28 Copyright © 2008, Oracle. All rights reserved.
Using plshprof
After you have the raw profiler output file, you can generate HTML reports for that run.
The plshprof utility has these options:
• -skip count: Skips the first count calls. Use only with the -trace symbol. The
default is 0.
SYSTOOLS
• -collect count: Collects information for count calls. Use only with -trace symbol.
The default is 1.
• -output filename: Specifies the name of the output file symbol.html or
tracefile1.html
• -summary: Prints only elapsed time. No default.
• -trace symbol: Specifies the function name of the tree root
Follow these steps to generate the HTML reports:
1. Change to the directory of the raw profiler output file. In the example shown in the slide,
the raw profiler file exists in the \Labs\labs folder. Its name is pd_dd_pkg.txt.
2. Run the plshprof utility. This utility accepts line arguments. The slide example
identifies that the output file should be named pd_cc_pkg.html and the original raw
profiler file is named pd_dd_pkg.txt.
SYSTOOLS
Resulting generated files:
SYSTOOLS
12 - 29 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
3. Open the filename.html in a browser:
SYSTOOLS
12 - 30 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
SYSTOOLS
12 - 31 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
and children report. The column that is in bold identifies how the report is sorted.
If a subprogram is nested, the profiler reports display the fully qualified name, such as
OE.P.A.B; that is, procedure B is nested within procedure A of package OE.P.
SYSTOOLS
SYSTOOLS
12 - 32 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
SYSTOOLS
12 - 33 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
summary report provides information about the total time spent in that namespace and the total
number of calls to functions in that namespace.
SYSTOOLS
SYSTOOLS
12 - 34 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
In this lesson, you should have learned how to:
• Trace PL/SQL program execution
• Profile PL/SQL applications
SYSTOOLS
12 - 35 Copyright © 2008, Oracle. All rights reserved.
Summary
In this lesson, you learned how to trace PL/SQL program execution by using the DBMS_TRACE
package and you learned to profile your PL/SQL application. With profiling, you learned how to
set up the profiler tables, generate raw data, and use DBMS_HPROF to analyze raw data to the
profiler tables.
SYSTOOLS
SYSTOOLS
This practice covers the following topics:
• Hierarchical profiling of PL/SQL code
SYSTOOLS
12 - 36 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
1. Generate profiling data for your CREDIT_CARD_PKG.
a. Re-create CREDIT_CARD_PKG by running the
D:\labs\labs\lab_12_01.sql script.
b. You need to identify the location of the profiler files. Create a DIRECTORY object to
identify this information.
CREATE DIRECTORY profile_data AS 'D:\Labs\labs';
c. Use DBMS_HPROF.START_PROFILING to start the profiler for your session.
d. Run your CREDIT_CARD_PKG.UPDATE_CARD_INFO with the following data.
credit_card_pkg.update_card_info
(154, 'Discover', '123456789');
e. Use DBMS_HPROF.STOP_PROFILING to stop the profiler.
@D:\app\Administrator\product\11.1.0\db_1\RDBMS\ADMIN\dbmshptab.sql
2. Run the dbmshptab.sql script that is located in the \home\rdbms\admin folder to
set up the profiler tables.
3. Use DBMS_HPROF.ANALYZE to analyze the raw data and write the information to the
SYSTOOLS
profiler tables.
a. Get the RUN_ID.
b. Query the DBMSHP_RUNS table to find top-level information for the RUN_ID that
you retrieved.
c. Query the DBMSHP_FUNCTION_INFO table to find information about each function
profiled.
4. Use the plshprof command-line utility to generate simple HTML reports directly from
the raw profiler data.
a. Open a command window.
b. Change the working directory to D:\labs\labs
c. Run the plshprof utility.
5. Open the report in your browser and review the data.
SYSTOOLS
SYSTOOLS
SYSTOOLS
SYSTOOLS
Safeguarding Your Code Against SQL
Injection Attacks
SYSTOOLS
Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Objectives
SYSTOOLS
After completing this lesson, you should be able to do the
following:
• Describe SQL injections
• Reduce attack surfaces
• Use DBMS_ASSERT
• Design immune code
• Test code for SQL injection flaws
SYSTOOLS
13 - 2 Copyright © 2008, Oracle. All rights reserved.
Objectives
In this lesson, you learn how to use techniques and tools to strengthen your code and
applications against SQL injection attacks.
SYSTOOLS
•
SYSTOOLS
Understanding SQL injection
• Reducing the attack surface
• Avoiding dynamic SQL
• Using bind arguments
• Filtering input with DBMS_ASSERT
• Designing code immune to SQL injections
• Testing code for SQL injection flaws
SYSTOOLS
13 - 3 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
SQL injection is a technique for maliciously exploiting
applications that use client-supplied data in SQL statements.
• Attackers trick the SQL engine into executing unintended
commands.
• SQL injection techniques may differ, but they all exploit a
single vulnerability in the application.
• To immunize your code against SQL injection attacks, use
bind arguments or validate and sanitize all input
concatenated to dynamic SQL.
SYSTOOLS
13 - 4 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
manipulate restricted data.
SQL injection techniques may differ, but they all exploit a single vulnerability in the application.
String literals that are incorrectly validated or not validated are concatenated into a dynamic
SQL statement and interpreted as code by the SQL engine.
To immunize your code against SQL injection attacks, you must use bind arguments (either
automatically with static SQL, or explicitly with dynamic SQL), or validate and sanitize all
input concatenated to dynamic SQL.
Although a program or an application may be vulnerable to SQL injection, Web applications are
at a higher risk, because an attacker can perpetrate SQL injection attacks without any database
or application authentication.
SYSTOOLS
Category Description
First Order Attack The attacker can simply enter a malicious string and cause
the modified code to be executed immediately.
Second Order Attack The attacker injects into persistent storage (such as a table
row), which is deemed a trusted source. An attack is
subsequently executed by another activity.
SYSTOOLS
13 - 5 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Researchers generally divide injection attacks into two categories:
• First Order Attack
• Second Order Attack
SQL injection attacks do not have to return data directly to the user to be useful. “Blind” attacks
(for example, that create a database user, but otherwise return no data) can still be very useful to
an attacker.
In addition, hackers are known to use timing or other performance indicators, and even error
messages in order to deduce the success or results of an attack.
SYSTOOLS
-- First order attack
CREATE OR REPLACE PROCEDURE GET_EMAIL
(p_last_name VARCHAR2 DEFAULT NULL) String literals that are
AS incorrectly validated or not
TYPE cv_custtyp IS REF CURSOR; validated are concatenated
cv cv_custtyp; into a dynamic SQL
v_email customers.cust_email%TYPE; statement, and interpreted
v_stmt VARCHAR2(400); as code by the SQL engine.
BEGIN
v_stmt := 'SELECT cust_email FROM customers
WHERE cust_last_name = '''|| p_last_name || '''';
DBMS_OUTPUT.PUT_LINE('SQL statement: ' || v_stmt);
OPEN cv FOR v_stmt;
LOOP
FETCH cv INTO v_email;
EXIT WHEN cv%NOTFOUND;
SYSTOOLS
DBMS_OUTPUT.PUT_LINE('Email: '||v_email);
END LOOP;
CLOSE cv;
EXCEPTION WHEN OTHERS THEN
dbms_output.PUT_LINE(sqlerrm);
dbms_output.PUT_LINE('SQL statement: ' || v_stmt);
END;
SYSTOOLS
Email: [email protected]
Email: [email protected]
SYSTOOLS Code
No Contains dynamic
SQL?
Yes
Uses bind
Yes arguments for all No
dynamic
components
SYSTOOLS
Yes Filters input
Safe
correctly?
No
Vulnerable
Assessing Vulnerability
You need to analyze your code to determine SQL injection vulnerability. The flowchart shows
you how to start assessing for vulnerability.
SYSTOOLS
Strategy
SYSTOOLS Description
Reduce the attack Ensure that all excess database privileges are revoked and that
surface only those routines that are intended for end-user access are
exposed. Though this does not entirely eliminate SQL injection
vulnerabilities, it does mitigate the impact of the attacks.
Avoid dynamic Dynamic SQL built with concatenated input values presents the
SQL with easiest entry point for SQL injections. Avoid constructing
concatenated input dynamic SQL this way.
Use bind Parameterize queries using bind arguments. Not only do bind
arguments arguments eliminate the possibility of SQL injections, they also
enhance performance.
SYSTOOLS
Filter and sanitize The Oracle-supplied DBMS_ASSERT package contains a number
input of functions that can be used to sanitize user input and to guard
against SQL injection in applications that use dynamic SQL built
with concatenated input values.
In case your filtering requirements cannot be satisfied by the
DBMS_ASSERT package, you may need to create your own filter.
SYSTOOLS
vulnerability itself. Not all methods are available for addressing every vulnerability.
Methods
• Use static SQL:
- If all Oracle identifiers (for example, column, table, view, trigger, program unit, or
schema names) are known at code compilation time
Note: Static SQL automatically binds arguments. Data definition language (DDL)
statements cannot be executed with static SQL.
• Use dynamic SQL with bind arguments:
- If any WHERE clause values, VALUES clause values, or SET clause values are
unknown, and any Oracle identifiers are unknown at code compilation time
Note: Use bind arguments for the values (the literals). Use string concatenation for the
validated and sanitized Oracle identifiers.
• Validate and sanitize input:
- If concatenating any strings and if bind arguments require additional filtering
AS
SYSTOOLS
CREATE OR REPLACE PROCEDURE GET_EMAIL
(p_last_name VARCHAR2 DEFAULT NULL)
This example avoids
BEGIN dynamic SQL with
FOR i IN concatenated input values.
(SELECT cust_email
FROM customers
WHERE cust_last_name = p_last_name)
LOOP
DBMS_OUTPUT.PUT_LINE('Email: '||i.cust_email);
END LOOP;
END;
EXECUTE get_email('Andrews')
Email: [email protected]
Email: [email protected]
SYSTOOLS
PL/SQL procedure successfully completed.
SYSTOOLS
•
SYSTOOLS
Understanding SQL injection
• Reducing the attack surface
• Avoiding dynamic SQL
• Using bind arguments
• Filtering input with DBMS_ASSERT
• Designing code immune to SQL injections
• Testing code for SQL injection flaws
SYSTOOLS
13 - 10 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
Using invoker’s rights:
• Using invoker’s rights helps to limit the privileges
• Helps to minimize the security exposure
-- this example does not use Invoker's rights
CONNECT /as sysdba
CREATE OR REPLACE 1
PROCEDURE change_password(p_username VARCHAR2 DEFAULT NULL,
p_new_password VARCHAR2 DEFAULT NULL)
IS
Note the use of dynamic SQL with
v_sql_stmt VARCHAR2(500);
concatenated input values.
BEGIN
SYSTOOLS
v_sql_stmt := 'ALTER USER '||p_username ||' IDENTIFIED BY '
|| p_new_password;
EXECUTE IMMEDIATE v_sql_stmt;
END change_password;
SYSTOOLS
Using Invoker’s Rights
Stored program units and SQL methods execute with a set of privileges. By default, the
privileges are those of a schema owner, also known as the definer. The definer’s rights not only
dictate the privileges, they are also used to resolve object references. If a program unit does not
need to be executed with the escalated privileges of the definer, you should specify that the
program unit executes with the privileges of a caller, also known as the invoker.
1. The example shown in the slide uses definer’s rights. Procedure CHANGE_PASSWORD is
created under the SYS schema. It accepts two parameters and uses them in the ALTER
USER statement.
2. SYS grants OE, HR, and SH the ability to execute the CHANGE_PASSWORD procedure.
SYSTOOLS
• OE is successful at changing the SYS password, because, by
default, CHANGE_PASSWORD executes with SYS privileges:
CONNECT oe
SYSTOOLS
IS
v_sql_stmt VARCHAR2(500);
BEGIN
v_sql_stmt := 'ALTER USER '||p_username ||' IDENTIFIED BY '
|| p_new_password;
EXECUTE IMMEDIATE v_sql_stmt;
END change_password;
SYSTOOLS
redefine the procedure with the invoker’s rights. This is done with the AUTHID
CURRENT_USER option.
CONNECT oe
ERROR at line 1:
ORA-01031: Insufficient privileges
ORA-06512: at "SYS.CHANGE_PASSWORD", at line 1
ORA-06512: at line 1
Now OE can no longer change the SYS (or any other account) password.
Notice that the CHANGE_PASSWORD procedure contains dynamic SQL with concatenated input
values. This is a SQL injection vulnerability. Although using invoker’s rights does not guarantee
the elimination of SQL injection risks, it can help mitigate the exposure.
SYSTOOLS
• Reduce the end-user interfaces to only those that are
actually needed.
– In a Web application, restrict users to accessing specified
Web pages.
– In a PL/SQL API, expose only those routines that are
intended for customer use.
• Where user input is required, make use of language features
to ensure that only data of the intended type can be
specified.
– Do not specify a VARCHAR2 parameter when it will be used as
SYSTOOLS
a number.
– Do not use numbers if you need only positive integers; use
natural instead.
SYSTOOLS
• In a PL/SQL API, expose only those routines that are intended for customer use.
Remove any debug, test, deprecated, or other unnecessary interfaces. They add nothing to
product functionality, but do provide an attacker with more ways to target your application.
From Oracle Database 10.2 and later, you can use PL/SQL conditional compilation for
managing self-tracing code, asserts, and so on.
Second, where user input is required, make use of language features to ensure that only data of
the intended type can be specified. For example:
• Do not specify a VARCHAR2 parameter when it will be used as a number.
• Do not use numbers if you need only positive integers, use natural instead.
Careful selection of parameter types to an API can considerably reduce the scope for attack, and
make it a lot easier for customers to use.
•
SYSTOOLS
Understanding SQL injection
• Reducing the attack surface
• Avoiding dynamic SQL
• Using bind arguments
• Filtering input with DBMS_ASSERT
• Designing code immune to SQL injections
• Testing code for SQL injection flaws
SYSTOOLS
13 - 14 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• Eliminates SQL injection vulnerability
• Creates schema object dependencies upon successful
compilation
• Can improve performance, when compared with DBMS_SQL
SYSTOOLS
13 - 15 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
would serve the purpose and be more secure:
• Handling a varying number of IN-list values in the query condition
• Handling the LIKE comparison operator in the query condition
SYSTOOLS
CREATE OR REPLACE PROCEDURE list_products_dynamic
(p_product_name VARCHAR2 DEFAULT NULL)
AS
TYPE cv_prodtyp IS REF CURSOR;
cv cv_prodtyp;
v_prodname product_information.product_name%TYPE;
v_minprice product_information.min_price%TYPE;
v_listprice product_information.list_price%TYPE;
You can convert this
v_stmt VARCHAR2(400);
statement to static SQL.
BEGIN
v_stmt := 'SELECT product_name, min_price, list_price
FROM product_information WHERE product_name LIKE
''%'||p_product_name||'%''';
OPEN cv FOR v_stmt;
dbms_output.put_line(v_stmt);
LOOP
SYSTOOLS
FETCH cv INTO v_prodname, v_minprice, v_listprice;
EXIT WHEN cv%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Product Info: '||v_prodname ||', '||
v_minprice ||', '|| v_listprice);
END LOOP;
CLOSE cv;
END;
SYSTOOLS
EXECUTE list_products_dynamic(''' and 1=0 union select
cast(username as varchar2(100)), null, null
from all_users --')
SYSTOOLS
• To use static SQL, accept the user input, and then
concatenate the necessary string to a local variable.
• Pass the local variable to the static SQL statement.
CREATE OR REPLACE PROCEDURE list_products_static
(p_product_name VARCHAR2 DEFAULT NULL)
AS
v_bind VARCHAR2(400);
BEGIN
v_bind := '%'||p_product_name||'%';
FOR i in
(SELECT product_name, min_price, list_price
FROM product_information
SYSTOOLS
WHERE product_name like v_bind)
LOOP
DBMS_OUTPUT.PUT_LINE('Product Info: '||i.product_name ||',
'|| i.min_price ||', '|| i.list_price);
END LOOP;
END list_products_static;
SYSTOOLS
EXECUTE list_products_static('Laptop')
Product Info: Laptop 128/12/56/v90/110, 2606, 3219
Product Info: Laptop 16/8/110, 800, 999
Product Info: Laptop 32/10/56, 1542, 1749
Product Info: Laptop 48/10/56/110, 2073, 2556
Product Info: Laptop 64/10/56/220, 2275, 2768
SYSTOOLS
• Dynamic SQL may be unavoidable in the following types of
situations:
– You do not know the full text of the SQL statements that must
be executed in a PL/SQL procedure.
– You want to execute DDL statements and other SQL
statements that are not supported in purely static SQL
programs.
– You want to write a program that can handle changes in data
definitions without the need to recompile.
• If you must use dynamic SQL, try not to construct it through
SYSTOOLS
concatenation of input values. Instead, use bind arguments.
SYSTOOLS
- You want to execute DDL statements and other SQL statements that are not supported
in purely static SQL programs.
- You want to write a program that can handle changes in data definitions without the
need to recompile.
• If you must use dynamic SQL, try not to construct it through concatenation of input values.
Instead, use bind arguments.
If you cannot avoid input concatenation, you must validate the input values, and also consider
constraining user input to a predefined list of values, preferably numeric values. Input filtering
and sanitizing are covered in more detail later in this lesson.
•
SYSTOOLS
Understanding SQL injection
• Reducing the attack surface
• Avoiding dynamic SQL
• Using bind arguments
• Filtering input with DBMS_ASSERT
• Designing code immune to SQL injections
• Testing code for SQL injection flaws
SYSTOOLS
13 - 19 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
You can rewrite the following statement
v_stmt :=
'SELECT '||filter(p_column_list)||' FROM customers '||
'WHERE account_mgr_id = '''|| p_sales_rep_id ||'''';
SYSTOOLS
'WHERE account_mgr_id = :1';
SYSTOOLS
comparison operators in the query condition.
SYSTOOLS
If you must use dynamic PL/SQL, try to use bind arguments.
For example, you can rewrite the following dynamic PL/SQL
with concatenated string values:
v_stmt :=
'BEGIN
get_phone (''' || p_fname ||
''','''|| p_lname ||'''); END;';
SYSTOOLS
v_stmt :=
'BEGIN
get_phone(:1, :2); END;';
SYSTOOLS
Working Around Bind Arguments
Though you should strive to use bind arguments with all dynamic SQL and PL/SQL statements,
there are instances where bind arguments cannot be used:
• DDL statements (such as CREATE, DROP, and ALTER)
• Oracle identifiers (such as names of columns, tables, schemas, database links, packages,
procedures, and functions)
If bind arguments cannot be used with dynamic SQL or PL/SQL, you must filter and sanitize all
input concatenated to the dynamic statement.
Next, you learn how to use the Oracle-supplied DBMS_ASSERT package functions to filter and
sanitize input values.
•
SYSTOOLS
Understanding SQL injection
• Reducing the attack surface
• Avoiding dynamic SQL
• Using bind arguments
• Filtering input with DBMS_ASSERT
• Designing code immune to SQL injections
• Testing code for SQL injection flaws
SYSTOOLS
13 - 22 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
DBMS_ASSERT functions:
Function Description
NOOP Does not perform any validation and returns the string
unchanged. Allows developers to mark some data as
trusted, and thereby, disable some SQL injection checks in
the source scanning tools. Avoid using this function unless
approved by the product security compliance team.
ENQUOTE_LITERAL Encloses string literal in single quotes
ENQUOTE_NAME Encloses string literal in double quotes
SIMPLE_SQL_NAME Verifies that the string is a simple SQL name
SYSTOOLS
QUALIFIED_SQL_NAME Verifies that the string is a qualified SQL name
SCHEMA_NAME Verifies that the string is an existing schema name
SQL_OBJECT_NAME Verifies that the string is a qualified identifier of an existing
SQL object
Understanding DBMS_ASSERT
To guard against SQL injection in applications that do not use bind arguments with dynamic
SQL, you must filter and sanitize concatenated strings. The primary use case for dynamic SQL
with string concatenation is when an Oracle identifier (such as a table name) is unknown at code
compilation time.
SYSTOOLS
DBMS_ASSERT is an Oracle-supplied PL/SQL package containing seven functions that can be
used to filter and sanitize input strings, particularly those that are meant to be used as Oracle
identifiers.
While two of these functions can be used to filter and sanitize any input strings, the majority of
them are specifically crafted to validate Oracle identifiers. They are the ENQUOTE_LITERAL
and the ENQUOTE_NAME functions. The other functions either do nothing (the NOOP function)
or return the input string unchanged if the verification algorithm does not raise any exceptions.
When using the DBMS_ASSERT package, always specify the SYS schema rather than relying on
a public synonym.
SYSTOOLS
• The object name used as an identifier:
SELECT count(*) records FROM orders;
SYSTOOLS
13 - 24 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
with a letter, and may be followed by letters, numbers, or a small set of special characters.
This is how identifiers are most often specified, and how object names are stored in data
dictionary tables.
• A quoted (or normal format) identifier begins and ends with double quotation marks. The
identifier can include almost any character within the double quotes. This format is user-
supplied.
SQL injection attacks can use the quoted method to attempt to subvert code that is written to
expect only the unquoted, more common, method.
•
SYSTOOLS
For your identifiers, determine:
1. Where will the input come from: user or data dictionary?
2. What verification is required?
3. How will the result be used, as an identifier or a literal value?
• These three factors affect:
– What preprocessing is required (if any) prior to calling the
verification functions
– Which DBMS_ASSERT verification function is required
– What post-processing is required before the identifier can
SYSTOOLS
actually be used
SYSTOOLS
followed by letters, numbers, or the special characters. Because of the restricted set of
characters that can be used in a basic SQL name, very little input or output formatting is
required.
• Simple: A simple SQL name is a basic SQL name, but also allows quotes to be used to
contain special characters.
• Qualified SQL name: A qualified SQL name is one or more simple SQL names that may
be followed by a database link.
Lastly, determine how the result will be used, as an identifier or a literal value.
Answering these questions will impact your preprocessing, post-processing, and the use of
DBMS_ASSERT.
SYSTOOLS
Identifier Type Verification
Basic Restrict applications to use only basic SQL names by
applying an algorithm similar to the TO_BASIC_SQL_NAME
function shown on the next few pages.
Simple DBMS_ASSERT.SIMPLE_SQL_NAME
Qualified DBMS_ASSERT.QUALIFIED_SQL_NAME
Database Link Use DBMS_ASSERT.QUALIFIED_SQL_NAME if you need to
filter only the input. However, if you need to confirm that a
link name is really a link name, use
DBMS_UTILITY.NAME_TOKENIZE.
SYSTOOLS
Schema DBMS_ASSERT.SCHEMA_NAME
Object Name DBMS_ASSERT.SQL_OBJECT_NAME
SYSTOOLS
1. Where the input will come from, the user or the data dictionary
2. What verification is required—does the object need to exist and if so, what type of identifier
is it?
3. How will the identifier be used, as an identifier or as a literal?
SYSTOOLS
This is a sample algorithm to trim white space. The code shown on the next page calls it.
-- this needs to be declared first:
CREATE OR REPLACE FUNCTION to_whitespace_trimmed
(i IN VARCHAR2)
RETURN VARCHAR2
AS
Space CONSTANT CHAR(1) := ' ';
Newline CONSTANT CHAR(1) := '
';
Tab CONSTANT CHAR(1) := Chr(9);
TYPE t IS TABLE OF VARCHAR2(10);
-- This is just an illustration; there may be others.
Whitespace_Characters CONSTANT t := t(Space, Newline, Tab);
v VARCHAR2(32767) := i;
BEGIN
DECLARE
Cur_Length PLS_INTEGER := Length(v);
SYSTOOLS
Prev_Length PLS_INTEGER := Cur_Length + 1;
BEGIN
WHILE Cur_Length < Prev_Length LOOP
Prev_Length := Cur_Length;
FOR j IN 1..Whitespace_Characters.Count() LOOP
v := Trim(BOTH Whitespace_Characters(j) FROM v);
END LOOP;
Cur_Length := Length(v);
END LOOP;
END;
RETURN v;
END to_whitespace_trimmed;
SYSTOOLS
SYSTOOLS
Use this code to convert to a basic SQL name:
CREATE OR REPLACE FUNCTION to_basic_sql_name
(p_user_input VARCHAR2)
RETURN VARCHAR2
AS
v_trimmed VARCHAR2(30);
v_temp VARCHAR2(30);
e_not_a_basic_identifier EXCEPTION;
PRAGMA Exception_Init(e_not_a_basic_identifier , -20001);
BEGIN
-- Whitespace is not significant (but note the need to use
-- the full set of whitespace characters, including tab,
-- space, newline).
v_trimmed := To_Whitespace_Trimmed(p_user_input);
SYSTOOLS
-- check that the string is upper case. If it
-- is then it may just be a quoted basic identifier
IF substr(v_trimmed,1,1) = '"' AND
substr(v_trimmed,length(v_trimmed),1) = '"' then
-- remove the quotes
v_temp := substr(v_trimmed,2,length(v_trimmed)-2);
IF nls_upper(v_temp) <> v_temp THEN
-- It isn't upper case so it's not a basic identifier
RAISE e_not_a_basic_identifier;
END IF;
ELSE
-- Not quoted so safe to convert to upper case
v_temp := nls_upper(v_trimmed);
END IF;
SYSTOOLS
IF regexp_like(v_temp, '\A[[:alpha:]]([[:alnum:]#$_])*$')
THEN
-- It is a basic identifier, return the formatted result
RETURN v_trimmed;
ELSE
RAISE e_not_a_basic_identifier;
END IF;
SYSTOOLS
• Do not perform unnecessary uppercase conversions on identifiers.
--Bad:
SAFE_SCHEMA := sys.dbms_assert.SCHEMA_NAME(UPPER(MY_SCHEMA));
--Good:
SAFE_SCHEMA := sys.dbms_assert.SCHEMA_NAME(MY_SCHEMA);
--Best:
SAFE_SCHEMA := sys.dbms_assert.ENQUOTE_NAME(
sys.dbms_assert.SCHEMA_NAME(MY_SCHEMA),FALSE);
SYSTOOLS
--Good:
tablename := sys.dbms_assert.ENQUOTE_NAME(tab_rec.table_name, FALSE);
--Note: If leading quotes are acceptable, then use
--the following construct:
safe := sys.dbms_assert.ENQUOTE_NAME('"'
||replace('"','""',input_with_leading_quotes) ||'"', FALSE);
DBMS_ASSERT Guidelines
Choosing the correct DBMS_ASSERT verification routines is important, and using them
correctly is just as important. The table shown in the slide identifies some usage guidelines.
Limitations
DBMS_ASSERT is not a panacea for all sorts of PL/SQL evils. It is essentially a collection of
SYSTOOLS
pattern-matching routines that confirm whether the supplied string matches expected patterns. It
can be used to protect against certain kinds of malicious input, but it cannot comprehensively
defend against all such inputs.
Here are some instances where DBMS_ASSERT may not help:
• It contains no routines to validate TNS connect strings, for example “((description =...”.
• It is not designed nor is it intended to be a defense against cross-site scripting attacks.
• It does not check for input string lengths, and therefore cannot be used as any kind of
defense against a buffer overflow attack.
• It does not guarantee that a SQL name is, in fact, a parseable SQL name.
• It does not protect against parsing as the wrong user or other security risks due to
inappropriate privilege management.
SYSTOOLS
• Avoid using ENQUOTE_NAME with user-supplied input unless
it is being used to supply the surrounding double quote for
SCHEMA_NAME.
• When using ENQUOTE_LITERAL, remember to escape
single quotes in the input.
-- Bad
EXECUTE IMMEDIATE 'begin'||
my_trace_routine('||sys.dbms_assert.ENQUOTE_LITERAL(
my_procedure_name)||');'||
'end';
SYSTOOLS
--Good
EXECUTE IMMEDIATE 'begin'||
my_trace_routine('||sys.dbms_assert.ENQUOTE_LITERAL(
replace(my_procedure_name,'''','''''')||');'||
'end';
SYSTOOLS
-- Bad
SQL_CMD := 'SELECT COUNT(*) FROM '||
sys.dbms_assert.QUALIFIED_SQL_NAME(p_process_order_table)
||' WHERE process_order = :1 ';
EXECUTE IMMEDIATE SQL_CMD INTO cnt USING p_process_order;
--Good
sys.dbms_utility.NAME_TOKENIZE(
sys.dbms_assert.QUALIFIED_SQL_NAME(p_process_order_table),
dummy, dummy, dummy, dblink, lastch);
IF dblink IS NOT NULL OR dblink <> '' THEN
RAISE DBLINK_ERROR; END IF;
-- p_process_order_table has already been verified
SQL_CMD := 'SELECT COUNT(*) FROM '|| p_process_order_table
||' WHERE process_order = :1 ';
EXECUTE IMMEDIATE SQL_CMD INTO cnt USING p_process_order;
SYSTOOLS
• Check and reject NULL or empty return results from
DBMS_ASSERT (test for NULL, '', and '""' ).
• Do not embed verification routines inside the injectable
string.
-- Bad
CREATE OR REPLACE PROCEDURE change_password7
(username VARCHAR2, password VARCHAR2)
AS
v_stmt VARCHAR2(2000);
BEGIN
v_stmt := 'alter user dbms_assert.ENQUOTE_NAME(
SYSTOOLS
dbms_assert.SCHEMA_NAME('''||username||''',FALSE)
identified by
dbms_assert.SIMPLE_SQL_NAME('''||password||''')';
dbms_output.put_line(v_stmt);
END;
SYSTOOLS
')
alter user dbms_assert.ENQUOTE_NAME(
dbms_assert.SCHEMA_NAME('HR',FALSE)
identified by dbms_assert.SIMPLE_SQL_NAME('test') quota unlimited on
system--')
PL/SQL procedure successfully completed.
By filtering and sanitizing the inputs before they are concatenated into the rest of the string,
exceptions would be raised if they are not valid.
CREATE OR REPLACE PROCEDURE change_password8
(username VARCHAR2, password VARCHAR2)
AS
v_stmt VARCHAR2(2000);
BEGIN
v_stmt := 'alter user '||sys.dbms_assert.ENQUOTE_NAME
(sys.dbms_assert.SCHEMA_NAME(username),FALSE)||
' identified by '||dbms_assert.SIMPLE_SQL_NAME(password);
dbms_output.put_line(v_stmt);
END;
Oracle Database 11g: Advanced PL/SQL 13 - 31
DBMS_ASSERT Guidelines
SYSTOOLS
• Protect all injectable parameters and code paths.
• Prefix all calls to DBMS_ASSERT with the owning schema,
SYS.
• If DBMS_ASSERT exceptions are raised from a number of
input strings, define and raise exceptions explicitly to ease
debugging during application development.
-- Bad
CREATE OR REPLACE PROCEDURE change_password3
(username VARCHAR2, password VARCHAR2)
AS
SYSTOOLS
BEGIN
...
EXCEPTION WHEN OTHERS THEN
RAISE;
END;
SYSTOOLS
ALTER SESSION SET Plsql_CCFlags = 'Tracing:true';
SYSTOOLS
• Oracle identifiers and keywords require special handling:
– Consider whether the user input can be constrained to a
simply checked identifier. For example, a table name
parameter might be constrained to 32 characters. This would
allow double quotes surrounding a 30-character string, the
maximum length for an Oracle identifier.
– Perform validation checks using bind arguments. For
example, select a table name from the ALL_TABLES view to
validate that the supplied value truly represents a valid table.
• Valid data may contain special SQL characters such as:
SYSTOOLS
– Single and double quotes
– Consecutive dashes (comments notation)
– Guillemets (double angle brackets such as <<block1>>
– Slash and asterisk (comments and hint notation)
SYSTOOLS
• Oracle identifiers and keywords require special handling.
• Valid data may contain special SQL characters.
• A danger of ‘escaping’ data is that the escape sequence may be truncated by a length limit
imposed on a buffer.
• Numeric and logical fields may also be attack vectors and need to be validated.
• Reliable comparison of characters may require negotiating character sets between the
system components (for example, the Web browser, the middle tier, and the back-end
server).
• Create a list of acceptable characters (known as a white list) and use regular expressions to
reject any characters that are not on the list.
• Avoid using a list of unacceptable characters (known as a black list), because it is always
possible to overlook an unacceptable character when defining the list. Also, an unacceptable
character can be represented in an alternate format to pass validation.
Before deploying your filters, you must obtain approval from the product security compliance
team.
Oracle Database 11g: Advanced PL/SQL 13 - 33
Lesson Agenda
•
SYSTOOLS
Understanding SQL injection
• Reducing the attack surface
• Avoiding dynamic SQL
• Using bind arguments
• Filtering input with DBMS_ASSERT
• Designing code immune to SQL injections
• Testing code for SQL injection flaws
SYSTOOLS
13 - 34 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• Most common vulnerability:
– Dynamic SQL with string concatenation
• Your code design needs to:
– Avoid input string concatenation in dynamic SQL
– Use bind arguments, whether automatically via static SQL or
explicitly via dynamic SQL statements
SYSTOOLS
13 - 35 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
As you have seen with the examples presented thus far, the common flaw of all code vulnerable
to SQL injection is the construction of dynamic SQL using string concatenation. Complete
immunity from SQL injection attack can be achieved only through the elimination of input
string concatenation in dynamic SQL.
• Avoid input string concatenation.
• Use bind arguments, whether automatically via static SQL or explicitly via dynamic SQL
statements.
Design your code to use bind arguments wherever possible. The only exceptions should be when
you need to concatenate identifiers or keywords, because you have no other choice.
SYSTOOLS
CREATE OR REPLACE PROCEDURE add_trigger
(p_schema VARCHAR2,p_table_name VARCHAR2) AS
v_stmt VARCHAR2(4000);
BEGIN
Note that by looking up the
object ID from the data
FOR o IN (SELECT object_id FROM all_objects dictionary using the user-
WHERE owner=p_schema AND supplied input in this static
object_type='TABLE' AND SQL statement, you are
object_name=p_table_name) LOOP essentially validating input.
v_stmt := 'CREATE OR REPLACE TRIGGER '
||sys.dbms_assert.enquote_name(
sys.dbms_assert.schema_name(p_schema),FALSE)
||'.'||sys.dbms_assert.enquote_name('XX$'||o.object_id)
||' AFTER UPDATE ON '||sys.dbms_assert.enquote_name(
sys.dbms_assert.schema_name(p_schema),FALSE)
||'.'||sys.dbms_assert.enquote_name(
sys.dbms_assert.simple_sql_name(p_table_name),FALSE)
SYSTOOLS
||' FOR EACH ROW Begin NULL; End;';
DBMS_OutPut.Put_Line('SQL stmt: ' || v_stmt);
EXECUTE IMMEDIATE v_stmt;
Use the DBMS_ASSERT
END LOOP;
functions to ensure that
EXCEPTION WHEN OTHERS THEN
correct identifier formatting
RAISE;
is preserved.
END;
SYSTOOLS
• Explicitly validate and enforce identifier length limits. Where the length limits are being
enforced, these limits should be clearly marked so that they can be changed easily if the
length limit does change in future Database releases.
• Take care to filter out control characters in user-supplied identifier names. Control
characters such as chr(10) (linefeed character) can generate spurious audit records.
• If an Oracle identifier needs to be generated based on a user-supplied identifier, avoid
concatenating the supplied identifier or using sequences to construct the generated Oracle
identifier name. Instead, consider looking up the object ID for the user-supplied identifier in
the data dictionary and using the object ID in the generated Oracle identifier name.
For example, you need to write a procedure that generates a trigger based on a table name. The
procedure accepts two parameters: the schema name and the table name.
The code shown on the slide can be used to generate Oracle identifiers based on user-supplied
identifiers. This example is continued on the next page.
SYSTOOLS
CONN / AS sysdba
EXEC sys.add_trigger('OE','TEST99')
SQL stmt: CREATE OR REPLACE TRIGGER "OE"."XX$76126" AFTER UPDATE ON
"OE"."TEST99" FOR EACH ROW Begin NULL; End;
SYSTOOLS
SELECT object_id, object_name FROM all_objects
WHERE object_type = 'TRIGGER' AND object_name like 'XX%'
AND owner = 'OE'; The ADD_TRIGGER
procedure generates Oracle
OBJECT_ID OBJECT_NAME
identifiers based on user-
---------- ------------------------------
supplied identifiers.
76128 XX$76126
SYSTOOLS
SYSTOOLS
• Give out privileges appropriately.
• Run code with invoker’s rights when possible.
• Ensure that the database privilege model is upheld when
using definer’s rights.
Invoker’s rights
SYSTOOLS
reviewed to ensure that the database privilege model is upheld.
If none of the methods of execution (definer’s rights, invoker’s rights) appears suitable, consider
implementing specific bypass checks for the duration of the call.
SYSTOOLS
• Filter parameter:
– P_WHERE_CLAUSE is a filter.
– It is difficult to protect against SQL injection.
stmt := 'SELECT session_id FROM sessions
WHERE' || p_where_clause;
• Prevention methods:
– Do not specify APIs that allow arbitrary query parameters to
be exposed.
– Any existing APIs with this type of functionality must be
SYSTOOLS
deprecated and replaced with safe alternatives.
SYSTOOLS
• Do not specify APIs that allow arbitrary query parameters to be exposed.
• Any existing APIs with this type of functionality must be deprecated and replaced with safe
alternatives.
If you must make use of filter parameters, contact your security compliance team for approval.
Any such routines must be registered as possible sinks of dynamic SQL and recorded in static
code analysis rulesets. This helps ensure that any users of these APIs are well behaved. Contact
your security compliance team to register these routines.
SYSTOOLS
• Design your code to trap and handle exceptions
appropriately.
• Before deploying your application:
– Remove all code tracing
– Remove all debug messages
SYSTOOLS
13 - 40 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Note: From Oracle Database 10.2 and later, you can use PL/SQL conditional compilation for
managing self-tracing code, asserts, and so on.
•
SYSTOOLS
Understanding SQL injection
• Reducing the attack surface
• Avoiding dynamic SQL
• Using bind arguments
• Filtering input with DBMS_ASSERT
• Designing code immune to SQL injections
• Testing code for SQL injection flaws
SYSTOOLS
13 - 41 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
• Test:
SYSTOOLS
– Dynamic testing
– Static testing
• Review:
– Peer and self reviews
– Analysis tools
SYSTOOLS
13 - 42 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
matter of creating and following routine procedure. Code reviews or walk-throughs are referred
to as “static testing,” whereas actually running the program with a given set of test cases in a
given development stage is often referred to as “dynamic testing.”
Testing for SQL injection flaws requires both static and dynamic testing. For static testing, you
can begin with a peer (or self) code review and/or make use of a static code analysis tool. After
finding and fixing the semantical SQL injection bugs, you must perform dynamic testing by
using tools that generate random input (fuzzing), and also run through test cases that you define
specifically for SQL injection detection within your code.
Language
PL/SQL
SYSTOOLS
Look for…
EXECUTE IMMEDIATE
OPEN cursor_var FOR ...
DBMS_SQL
DBMS_SYS_SQL
C String substitutions such as:
static const oratext createsq[] =
"CREATE SEQUENCE \"%.*s\".\"%.*s\" start with %.*s
increment by
%.*s";
SYSTOOLS
seqnaml, seqnam, sizeof(start), start,
sinc_byl, sincrement_by);
Java String concatenations such as:
sqltext = "DROP VIEW " + this.username + "." +
this.viewName;
Reviewing Code
When reviewing code, first identify all dynamic SQL statements. Depending on your
programming language, some key indicators that dynamic SQL is in use are shown in the slide.
Next, check to make sure that bind arguments are used in all possible and practical instances.
Where bind arguments cannot be used, make sure that the correct routines are used to filter and
SYSTOOLS
sanitize inputs.
•
SYSTOOLS
Generally performed by an automated tool
• Can be performed on some versions of the source code
• Can be performed on some forms of the object code
• Should be used as one of the initial steps of testing code
SYSTOOLS
13 - 44 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Because SQL injections arise from dynamically generated SQL, static code analysis tools may
have a hard job identifying all categories of SQL injection with some certainty, because this may
require knowledge of object names and contents not available at analysis time. For example, a
PL/SQL function might construct a string containing parts of a SQL statement that might then be
combined with a malicious table name, thereby leading to an injection.
Static code analysis tools should not be used for any kind of security sign-off. Instead, it should
be one of the initial steps in the code testing process.
SYSTOOLS
• Is a software testing technique that provides random data
(“fuzz”) to the inputs of a program.
• Can enhance software security and software safety,
because it often finds odd oversights and defects that human
testers would fail to find.
• Must not be used as a substitute for exhaustive testing or
formal methods.
• While tools can be used to automate fuzz testing, it may be
necessary to customize the test data and application context
SYSTOOLS
to get the best results from such tools.
SYSTOOLS
Fuzz testing is thought to enhance software security and software safety, because it often finds
odd oversights and defects that human testers would fail to find, and even careful human test
designers would fail to create tests for.
However, fuzz testing is not a substitute for exhaustive testing or formal methods; it can only
provide a random sample of the system’s behavior, and in many cases passing a fuzz test may
only demonstrate that a piece of software handles exceptions without crashing, rather than
behaving correctly. Thus, fuzz testing can be regarded only as a bug-finding tool rather than an
assurance of quality.
While tools can be used to automate fuzz testing, it may be necessary to customize the test data
and application context to get the best results from such tools.
SYSTOOLS
• Test each input parameter individually.
• When testing each parameter, leave all the other parameters
unchanged with valid data as their arguments.
• Omitting parameters or supplying bad arguments to other
parameters while you are testing another for SQL injection
can break the application in ways that prevent you from
determining whether SQL injection is possible.
• Always use the full parameter line, supplying every
parameter, except the one that you are testing, with a
SYSTOOLS
legitimate value.
• Certain object and schema names help you uncover SQL
injection vulnerabilities.
SYSTOOLS
simpler, particularly with applications that have parameter lines going into many thousands of
characters. Omitting parameters or supplying bad arguments to other parameters while you are
testing another for SQL injection can break the application in ways that prevent you from
determining whether SQL injection is possible.
So, when testing for SQL injection, always use the full parameter line, supplying every
parameter, except the one that you are testing, with a legitimate value.
Certain object and schema names help you uncover SQL injection vulnerabilities. On the next
page is a list of names as input values in your tests.
Name Test
SYSTOOLS
AAAAAAAAAABBBB
BBBBBBCCCCCCCCC
Maximum size identifiers should be tested as both schema and
object names. Checks that temporary object names can be
created.
AAAAAAAAAAAAAA Maximum and “nearly” maximum object names should be
AAAAAAAAAAAAAA handled as separate objects. Checks that any name truncation
AA & operation does not result in non-unique names.
AAAAAAAAAAAAAA
AAAAAAAAAAAAAA
A
schema1.a Ensures that objects with the same name in different schemas
schema2.a are properly differentiated.
AAA Ensures that objects with different case names are clearly
"aaa" differentiated.
SYSTOOLS
object@dblink
Rename "ABC"
Ensures that link names (both valid and invalid) do not defeat
security tests. Ensure that links are rejected unless specifically
allowable.
Renames objects during tests to ensure that applications
to "XYZ" continue to function correctly.
"quoted" Ensures that quoted schema and object names can be handled.
SYSTOOLS
"A%TYPE" Refers to an object and not an object attribute.
"a/*X*/
<<A>>,%s<img>--
Ensures that special characters in quoted variables do not have
%00\0AAA ", other side effects.
"a' '''||*/
.@\?:x&y}{)(><][!=;A"
"xxx"||chr(8)||"yyy",
"xxx"||chr(9)||"yyy",
Ensures that object names with embedded control characters are
"xxx"||chr(10)||"yyy", handled correctly. Checks that all output correctly distinguishes
"xxx"||chr(13)||"yyy",
"xxx"||chr(4)||"yyy",
these objects, especially any output written to files.
"xxx"||chr(26)||"yyy", Note that some object names may be (correctly) rejected as
"xxx"||chr(0)||"yyy" invalid syntax.
NULL Null and empty strings may behave differently on different
Oracle Database ports or versions.
SYSTOOLS
In this lesson, you should have learned how to:
• Detect SQL injection vulnerabilities
• Reduce attack surfaces
• Use DBMS_ASSERT
• Design immune code
• Test code for SQL injection flaws
SYSTOOLS
13 - 48 Copyright © 2008, Oracle. All rights reserved.
Summary
In this lesson, you learned how to use techniques and tools to strengthen your code and
applications against SQL injection attacks.
SYSTOOLS
SYSTOOLS
This practice covers the following topics:
• Testing your knowledge of SQL injection
• Rewriting code to protect against SQL injection
SYSTOOLS
13 - 49 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
Answer the following questions to test your knowledge about how to reduce attack surface.
1. Only code that is used in Web applications is vulnerable to SQL injection attack.
True/False
2. Code that is most vulnerable to SQL injection attack contains (check all that apply):
Input parameters
SYSTOOLS
3. By default, a stored procedure or SQL method executes with the privileges of the owner
(definer’s rights).
True/False
4. By using AUTHID CURRENT_USER in your code, you are (check all that apply):
Specifying that the code executes with the highest privilege level
SYSTOOLS
Not eliminating all possible SQL injection vulnerabilities
5. Match each attack surface reduction technique with an example of the technique.
Technique Example
SYSTOOLS
6. Examine this code. Run the lab_13_06.sql script to create the procedure.
CREATE OR REPLACE PROCEDURE get_income_level (p_email
VARCHAR2 DEFAULT NULL)
IS
TYPE cv_custtyp IS REF CURSOR;
cv cv_custtyp;
v_income customers.income_level%TYPE;
v_stmt VARCHAR2(400);
BEGIN
v_stmt := 'SELECT income_level FROM customers WHERE
cust_email = '''
|| p_email || '''';
SYSTOOLS
FETCH cv INTO v_income;
EXIT WHEN cv%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Income level is: '||v_income);
END LOOP;
CLOSE cv;
exec get_income_level('[email protected]')
SYSTOOLS
exec get_income_level('x'' union select username from
all_users where ''x''=''x')
SYSTOOLS
7. Rewrite the code to protect against SQL injection. You can run the lab_13_07.sql
script to re-create the procedure.
SYSTOOLS
To play a viewlet, double-click the les13_staticsql.htm file that is located in the
D:\labs\viewlets folder. When prompted, click Start.
SYSTOOLS
SYSTOOLS
SYSTOOLS
Table of Contents
SYSTOOLS
Practices for Lesson 1 ......................................................................................................... 3
Practice 1-1: Introduction ............................................................................................... 3
Practices for Lesson 2 ....................................................................................................... 16
Practice 2-1: PL/SQL Review....................................................................................... 16
Practices for Lesson 3 ....................................................................................................... 21
Practice 3-1: Designing PL/SQL Code ......................................................................... 21
Practices for Lesson 4 ....................................................................................................... 24
Practice 4-1: Working with Collections........................................................................ 24
Practices for Lesson 5 ....................................................................................................... 32
Practice 5-1: Using Advanced Interface Methods ........................................................ 32
Practices for Lesson 6 ....................................................................................................... 36
Practice 6-1: Implementing Fine-Grained Access Control for VPD ............................ 36
Practices for Lesson 7 ....................................................................................................... 41
Practice 7-1: Manipulating Large Objects .................................................................... 41
Practices for Lesson 8 ....................................................................................................... 47
SYSTOOLS
Practice 8-1: Using SecureFile Format LOBs .............................................................. 47
Practices for Lesson 9 ....................................................................................................... 56
Practice 9-1: Performance and Tuning ......................................................................... 56
Practices for Lesson 10 ..................................................................................................... 66
Practice 10-1: Improving Performance with Caching .................................................. 66
Practices for Lesson 11 ..................................................................................................... 71
Practice 11-1: Analyzing Your Code............................................................................ 71
Practices for Lesson 12 ..................................................................................................... 79
Practice 12-1: Profiling and Tracing............................................................................. 79
Practices for Lesson 13 ..................................................................................................... 84
Practice 13-1: Safeguarding Your Code Against SQL Injection Attacks..................... 84
SYSTOOLS
SYSTOOLS
Practice 1-1: Introduction
In this practice, you review the available Oracle SQL Developer resources. You also
learn about the user account that you use in this course. You then start Oracle SQL
Developer, create a new database connection, and browse your SH and HR tables. You
also set some Oracle SQL Developer preferences, execute SQL statements, and access
and bookmark the Oracle Database 11g documentation and other useful Web sites that
you can use in this course.
SYSTOOLS
The Oracle SQL Developer Home page appears as follows:
SYSTOOLS
SYSTOOLS
SYSTOOLS
SYSTOOLS
icon onto the Links toolbar. The link is added to your Links toolbar as follows:
SYSTOOLS
SYSTOOLS
4) Access the Oracle SQL Developer tutorial, which is available online at:
http://st-curriculum.oracle.com/tutorial/SQLDeveloper/index.htm
Access the Oracle SQL Developer tutorial by using the preceding URL. The
following page appears:
SYSTOOLS
SYSTOOLS
To review the section on creating a database connection, click the plus sign (+)
next to the “What to Do First” link to display the “Creating a Database
Connection” link. To review the Creating a Database Connection topic, click the
topic’s link. To review the section on accessing data, click the plus sign (+) next
to the “Accessing Data” link to display the list of available topics. To review any
of the topics, click the topic’s link.
SYSTOOLS
7) Create a database connection to SH schema using the following information:
a) Connection Name: sh_connection
b) Username: sh
c) Password: sh
d) Hostname: localhost
e) Port: 1521
f) SID: orcl
Right-click the Connections icon on the Connections tabbed page, and then
SYSTOOLS
select the New Connection option from the shortcut menu. The New/Select
Database Connection window appears. Use the preceding information to create
the new database connection.
Note: To display the properties of the newly created connection, right-click the
connection name, and then select Properties from the shortcut menu. Enter the
username, password, host name, and service name with the appropriate
information, as provided above. The following is a sample of the newly created
database connection for the SH schema using a local connection:
SYSTOOLS
SYSTOOLS
8) Test the new connection. If the Status is Success, connect to the database using this
new connection.
a) Double-click the sh_connection icon on the Connections tabbed page.
b) Click the Test button in the New/Select Database Connection window. If the
status is Success, click the Connect button.
SYSTOOLS
SYSTOOLS
SYSTOOLS
9) Create a new database connection named hr_connection.
a) Right-click the sh_connection connection in the Object Navigation tree, and
select the Properties menu option.
b) Enter hr_connection as the connection name and hr as the username and
password, and then click Save to create the new connection.
c) Repeat step 8 to test the new hr_connection connection.
SYSTOOLS
SYSTOOLS
SYSTOOLS
10) Repeat step 9 to create and test a new database connection named
oe_connection. Enter oe as the database connection username and password.
SYSTOOLS
SYSTOOLS
SYSTOOLS
11) Repeat step 9 to create and test a new database connection named
sys_connection. Enter sys in the Username field, oracle in the Password
field, and SYSDBA as the role.
SYSTOOLS
SYSTOOLS
SYSTOOLS
From the Role drop-down menu, select SYSDBA as the role.
SYSTOOLS
Double-click the EMPLOYEES table. The Columns tab displays the columns in
the EMPLOYEES table as follows:
SYSTOOLS
SYSTOOLS
13) Browse the EMPLOYEES table and display its data.
To display the employee data, click the Data tab. The EMPLOYEES table data is
displayed as follows:
SYSTOOLS
SYSTOOLS
SYSTOOLS
14) Use the SQL Worksheet to select the last names and salaries of all employees whose
annual salary is greater than $10,000. Use both the Execute Statement (F9) and the
Run Script (F5) icons to execute the SELECT statement. Review the results of both
methods of executing the SELECT statements on the appropriate tabs.
Note: Take a few minutes to familiarize yourself with the data, or consult Appendix
B, “Table Descriptions,” which provides the description and data for all tables in the
HR, SH, and OE schemas that you will use in this course.
SYSTOOLS
Display the SQL Worksheet by using any of the following two methods:
Select Tools > SQL Worksheet, or click the Open SQL Worksheet icon. The
Select Connection window appears. Enter the following statement in the SQL
Worksheet:
SELECT *
FROM employees
WHERE SALARY > 10000;
15) Create and execute a simple anonymous block that outputs “Hello World.”
SYSTOOLS
Click the DBMS_OUTPUT tab, and then click the Enable DBMS Output
icon as follows:
b) Use the SQL Worksheet area to enter the code for your anonymous block.
SYSTOOLS
c) Click the Run Script icon (F5) to run the anonymous block.
The Script Output tab displays the output of the anonymous block as
follows:
SYSTOOLS
16) Browse the structure of the SALES table in the SH schema and display its data.
a) Double-click the sh_connection database connection.
b) Expand the Tables icon by clicking the plus sign.
SYSTOOLS
Double-click the SALES table. The Columns tab displays the columns in the
SALES table. To display the sales data, click the Data tab. The SALES table
data is displayed.
17) Browse the structure of the ORDERS table in the OE schema and display its data.
a) Double-click the oe_connection database connection.
b) Expand the Tables icon by clicking the plus sign.
c) Display the structure of the ORDERS table.
d) Browse the ORDERS table and display its data.
Double-click the ORDERS table. The Columns tab displays the columns in
the ORDERS table. To display the order data, click the Data tab. The ORDERS
table data is displayed.
SYSTOOLS
Accessing the Oracle Database 11g, Release 1 Online Documentation Library
18) Access the Oracle Database 11g Release documentation Web page at:
http://www.oracle.com/pls/db111/homepage
19) Bookmark the page for easier future access.
20) Display the complete list of books available for Oracle Database 11g, Release 1.
21) Make a note of the following documentation references that you will use in this
course as needed:
a) Oracle Database 2 Day + Data Warehousing Guide 11g Release 1 (11.1)
b) Oracle Database Data Warehousing Guide 11g Release 1 (11.1)
c) Oracle Database SQL Developer User's Guide Release 1.2
SYSTOOLS
d) Oracle Database Reference 11g Release 1 (11.1)
e) Oracle Database New Features Guide 11g Release 1 (11.1)
f) Oracle Database SQL Language Reference 11g Release 1 (11.1)
g) SQL*Plus User's Guide and Reference Release 11.1
h) Oracle Database SQLJ Developer's Guide and Reference 11g Release 1 (11.1)
i) Oracle Database Concepts 11g Release 1 (11.1)
j) Oracle Database Sample Schemas 11g Release 1 (11.1)
SYSTOOLS
Practice 2-1: PL/SQL Review
In this practice, you test and review your PL/SQL knowledge.
PL/SQL Basics
1) What are the four key areas of the basic PL/SQL block? What happens in each area?
Header section: Names the program unit and identifies it as a procedure,
function, or package; also identifies any parameters that the code may use.
Executable section: Main processing area of the PL/SQL program; starts with
the keyword BEGIN.
SYSTOOLS
Exception handler section: Optional error handling section; starts with the
keyword EXCEPTION.
2) What is a variable and where is it declared?
Variables are used to store data during PL/SQL block execution. You can
declare variables in the declarative part of any PL/SQL block, subprogram, or
package. Declarations allocate storage space for a value, specify its data type,
and name the storage location so that you can reference it. Declarations can also
assign an initial value and impose the NOT NULL constraint on the variable.
Syntax: variable_name datatype[(size)][:= initial_value];
3) What is a constant and where is it declared?
Constants are variables that never change. Constants are declared and assigned
a value in the declarative section, before the executable section.
Syntax: constant_name CONSTANT datatype[(size)] :=
initial_value;
SYSTOOLS
4) What are the different modes for parameters and what does each mode do?
There are three parameter modes: IN, OUT, and IN OUT. IN is the default and
it means a value is passed into the subprogram. The OUT mode indicates that the
subprogram is passing a value generated in the subprogram out to the calling
environment. The IN OUT mode means that a value is passed into the
subprogram. The subprogram may change the value and pass the value out to
the calling environment.
SYSTOOLS
called differently than procedures. They are called as an expression embedded
within another command. Procedures are called as statements.
6) What are the two main components of a PL/SQL package?
The package body and the package specification
a) In what order are they defined?
First the package specification, and then the package body
b) Are both required?
No, only a package specification is required. A specification can exist without a
body, but a body cannot exist as valid without the specification.
7) How does the syntax of a SELECT statement used within a PL/SQL block differ from
a SELECT statement issued in SQL*Plus?
SYSTOOLS
The INTO clause is required with a SELECT statement that is in a PL/SQL
subprogram.
8) What is a record?
A record is a composite type that has internal components, which can be
manipulated individually. Use the RECORD data type to treat related but
dissimilar data as a logical unit.
9) What is an index-by table?
Index-by tables are a data structure declared in a PL/SQL block. It is similar to
an array and comprises two components—the index and the data field. The data
field is a column of a scalar or record data type, which stores the INDEX BY
table elements.
10) How are loops implemented in PL/SQL?
Looping constructs are used to repeat a statement or sequence of statements
SYSTOOLS
multiple times. PL/SQL has three looping constructs:
- Basic loops that perform repetitive actions without overall conditions
- FOR loops that perform iterative control of actions based on a count
- WHILE loops that perform iterative control of actions based on a condition
11) How is branching logic implemented in PL/SQL?
You can change the logical flow of statements within the PL/SQL block with a
number of control structures. Branching logic is implemented within PL/SQL by
using the conditional IF statement or CASE expressions.
Cursor Basics
SYSTOOLS
12) What is an explicit cursor?
The Oracle server uses work areas, called private SQL areas, to execute SQL
statements and to store processing information. You can use PL/SQL cursors to
name a private SQL area and access its stored information. Use explicit cursors
to individually process each row returned by a multiple-row SELECT statement.
13) Where do you define an explicit cursor?
A cursor is defined in the declarative section.
14) Name the five steps for using an explicit cursor.
Declare, Open, Fetch, Test for existing rows, and Close
15) What is the syntax used to declare a cursor?
CURSOR cursor_name IS SELECT_statement
16) What does the FOR UPDATE clause do within a cursor definition?
SYSTOOLS
The FOR UPDATE clause locks the rows selected in the SELECT statement
definition of the cursor.
17) What command opens an explicit cursor?
OPEN cursor_name;
18) What command closes an explicit cursor?
CLOSE cursor_name;
19) Name five implicit actions that a cursor FOR loop provides.
Declares a record structure to match the select list of the cursor; opens the
cursor; fetches from the cursor; exits the loop when the fetch returns no row;
and closes the cursor
20) Describe what the following cursor attributes do:
SYSTOOLS
%ISOPEN: Returns a Boolean value indicating whether the cursor is open
%FOUND: Returns a Boolean value indicating whether the last fetch returned a
value
%NOTFOUND: Returns a Boolean value indicating whether the last fetch did not
return a value
%ROWCOUNT: Returns an integer indicating the number of rows fetched so far
Exceptions
SYSTOOLS
21) An exception occurs in your PL/SQL block, which is enclosed in another PL/SQL
block. What happens to this exception?
Control is passed to the exception handler. If the exception is handled in the
inner block, processing continues to the outer block. If the exception is not
handled in the inner block, an exception is raised in the outer block and control
is passed to the exception handler of the outer block. If neither the inner nor the
outer block traps the exception, the program ends unsuccessfully.
22) An exception handler is mandatory within a PL/SQL subprogram. (True/False)
False
23) What syntax do you use in the exception handler area of a subprogram?
EXCEPTION
WHEN named_exception THEN
statement[s];
SYSTOOLS
WHEN others THEN
statement[s];
END;
24) How do you code for a NO_DATA_FOUND error?
EXCEPTION
WHEN no_data_found THEN
statement[s];
END;
25) Name three types of exceptions.
User-defined, Oracle server predefined, and Oracle server non-predefined
26) To associate an exception identifier with an Oracle error code, what pragma do you
use and where?
Use the PRAGMA EXCEPTION_INIT and place the PRAGMA
SYSTOOLS
EXCEPTION_INIT in the declarative section.
27) How do you explicitly raise an exception?
Use the RAISE statement or the raise_application_error procedure.
28) What types of exceptions are implicitly raised?
All Oracle server exceptions (predefined and non-predefined) are automatically
raised.
29) What does the RAISE_APPLICATION_ERROR procedure do?
It enables you to issue user-defined error messages from subprograms.
Dependencies
SYSTOOLS
30) Which objects can a procedure or function directly reference?
Table, view, sequence, procedure, function, package specification, object
specification, and collection type
31) What are the two statuses that a schema object can have and where are they recorded?
The user_objects dictionary view contains a column called status. Its values
are VALID and INVALID.
32) The Oracle server automatically recompiles invalid procedures when they are called
from the same ______. To avoid compile problems with remote database calls, you
can use the ________ model instead of the timestamp model.
database
signature
33) Which data dictionary contains information on direct dependencies?
SYSTOOLS
user_dependencies
34) Which script do you run to create the views deptree and ideptree?
You use the utldtree.sql script.
35) What does the deptree_fill procedure do and what are the arguments that you
need to provide?
The deptree_fill procedure populates the deptree and ideptree views
to display a tabular representation of all dependent objects, direct and indirect.
You pass the object type, object owner, and object name to the deptree_fill
procedure.
36) What does the dbms_output package do?
The dbms_output package enables you to send messages from stored
procedures, packages, and triggers.
SYSTOOLS
37) How do you write “This procedure works.” from within a PL/SQL program by using
dbms_output?
DBMS_OUTPUT.PUT_LINE('This procedure works.');
38) What does dbms_sql do and how does it compare with Native Dynamic SQL?
dbms_sql enables you to embed dynamic data manipulation language (DML),
data definition language (DDL), and data control language (DCL) statements
within a PL/SQL program. Native dynamic SQL allows you to place dynamic
SQL statements directly into PL/SQL blocks. Native dynamic SQL in PL/SQL is
easier to use than dbms_sql, requires much less application code, and performs
better.
SYSTOOLS
Practice 3-1: Designing PL/SQL Code
In this practice, you determine the output of a PL/SQL code snippet and modify the
snippet to improve the performance. Next, you implement subtypes and use cursor
variables to pass values to and from a package. Files mentioned in the practice exercises
are found in the /labs folder. Connect as OE to perform the steps.
1) Determine the output of the following code snippet in the lab_03_01.sql file.
Connect as OE.
SET SERVEROUTPUT ON
BEGIN
UPDATE orders SET order_status = order_status;
FOR v_rec IN ( SELECT order_id FROM orders )
LOOP
SYSTOOLS
IF SQL%ISOPEN THEN
DBMS_OUTPUT.PUT_LINE('TRUE – ' || SQL%ROWCOUNT);
ELSE
DBMS_OUTPUT.PUT_LINE('FALSE – ' || SQL%ROWCOUNT);
END IF;
END LOOP;
END;
/
Execute the code from the lab_03_01.sql file. It will show FALSE – 105
for each row fetched.
2) Modify the following snippet of code in the lab_03_02.sql file to make better
use of the FOR UPDATE clause and improve the performance of the program.
DECLARE
CURSOR cur_update
SYSTOOLS
IS SELECT * FROM customers
WHERE credit_limit < 5000 FOR UPDATE;
BEGIN
FOR v_rec IN cur_update
LOOP
IF v_rec IS NOT NULL THEN
UPDATE customers
SET credit_limit = credit_limit + 200
WHERE customer_id = v_rec.customer_id;
END IF;
END LOOP;
END;
/
DECLARE
SYSTOOLS
CURSOR cur_update
IS SELECT * FROM customers
WHERE credit_limit < 5000 FOR UPDATE;
BEGIN
FOR v_rec IN cur_update
LOOP
UPDATE customers
SET credit_limit = credit_limit + 200
WHERE CURRENT OF cur_update;
END LOOP;
END;
/
Alternatively, you can execute the code from the sol_03_02.sql file.
SYSTOOLS
3) Create a package specification that defines subtypes, which can be used for the
warranty_period field of the product_information table. Name this
package MY_TYPES. The type needs to hold the month and year for a warranty
period.
CREATE OR REPLACE PACKAGE mytypes
IS
TYPE typ_warranty
IS RECORD (month POSITIVE, year PLS_INTEGER);
SUBTYPE warranty IS typ_warranty; -- based on RECORD type
END mytypes;
/
SYSTOOLS
4) Create a package named SHOW_DETAILS that contains two subroutines. The first
subroutine should show order details for the given order_id. The second
subroutine should show customer details for the given customer_id, including the
customer ID, first name, phone numbers, credit limit, and email address.
Both subroutines should use the cursor variable to return the necessary details.
SYSTOOLS
CREATE OR REPLACE PACKAGE show_details AS
SYSTOOLS
rt_cust);
END show_details;
/
PROCEDURE get_cust
(p_custid IN NUMBER, p_cv_cust IN OUT rt_cust)
SYSTOOLS
IS
BEGIN
OPEN p_cv_cust FOR
SELECT customer_id, cust_first_name, phone_numbers,
credit_limit,
cust_email FROM customers
WHERE customer_id = p_custid;
-- CLOSE p_cv_cust
END get_cust;
END;
/
Alternatively, you can execute the code from the sol_03_04.sql file.
SYSTOOLS
Practice 4-1: Working with Collections
In this practice, you create a nested table collection and use PL/SQL code to manipulate
the collection.
Analyzing Collections
1) Examine the following definitions. Run the lab_04_01.sql script to create these
objects.
CREATE TYPE typ_item AS OBJECT --create object
(prodid NUMBER(5),
price NUMBER(7,2) )
/
CREATE TYPE typ_item_nst -- define nested table type
SYSTOOLS
AS TABLE OF typ_item
/
CREATE TABLE pOrder ( -- create database table
ordid NUMBER(5),
supplier NUMBER(5),
requester NUMBER(4),
ordered DATE,
items typ_item_nst)
NESTED TABLE items STORE AS item_stor_tab
/
@lab_04_01.sql
2) The following code generates an error. Run the lab_04_02.sql script to generate
and view the error.
BEGIN
SYSTOOLS
-- Insert an order
INSERT INTO pOrder
(ordid, supplier, requester, ordered, items)
VALUES (1000, 12345, 9876, SYSDATE, NULL);
-- insert the items for the order created
INSERT INTO TABLE (SELECT items
FROM pOrder
WHERE ordid = 1000)
VALUES(typ_item(99, 129.00));
END;
/
@lab_04_02.sql
SYSTOOLS
The error “ORA-22908: reference to NULL table value” results from setting the
table columns to NULL.
b) How can you fix the error?
You should always use a nested table’s default constructor to initialize it:
SYSTOOLS
typ_item_nst(typ_item(99, 129.00)));
END;
/
BEGIN
-- Insert an order
INSERT INTO pOrder
(ordid, supplier, requester, ordered, items)
VALUES (1000, 12345, 9876, SYSDATE, null);
-- Once the nested table is set to null, use the update
-- update statement
UPDATE pOrder
SYSTOOLS
SET items = typ_item_nst(typ_item(99, 129.00))
WHERE ordid = 1000;
END;
/
3) Examine the following code. This code produces an error. Which line causes the
error, and how do you fix it?
(Note: You can run the lab_04_03.sql script to view the error output.)
SYSTOOLS
DECLARE
TYPE credit_card_typ
IS VARRAY(100) OF VARCHAR2(30);
BEGIN
v_mc.EXTEND;
v_visa.EXTEND;
v_am.EXTEND;
v_disc.EXTEND;
v_dc.EXTEND;
SYSTOOLS
END;
/
Using Collections
In the following practice exercises, you implement a nested table column in the
CUSTOMERS table and write PL/SQL code to manipulate the nested table.
SYSTOOLS
(card_type VARCHAR2(25),
card_num NUMBER);
/
SYSTOOLS
ALTER TABLE customers ADD
(credit_cards typ_cr_card_nst)
NESTED TABLE credit_cards STORE AD c_c_store_tab;
SYSTOOLS
PROCEDURE display_card_info
(p_cust_id NUMBER);
END credit_card_pkg; -- package spec
/
PROCEDURE update_card_info
(p_cust_id NUMBER, p_card_type VARCHAR2, p_card_no
VARCHAR2)
IS
v_card_info typ_cr_card_nst;
i INTEGER;
BEGIN
SELECT credit_cards
INTO v_card_info
SYSTOOLS
FROM customers
WHERE customer_id = p_cust_id;
IF v_card_info.EXISTS(1) THEN
-- cards exist, add more
PROCEDURE display_card_info
(p_cust_id NUMBER)
IS
SYSTOOLS
SELECT credit_cards
INTO v_card_info
FROM customers
WHERE customer_id = p_cust_id;
END display_card_info;
END credit_card_pkg; -- package body
/
IS
SYSTOOLS
CREATE OR REPLACE PACKAGE credit_card_pkg
PROCEDURE update_card_info
(p_cust_id NUMBER, p_card_type VARCHAR2, p_card_no
VARCHAR2);
PROCEDURE display_card_info
(p_cust_id NUMBER);
END credit_card_pkg; -- package spec
/
PROCEDURE update_card_info
(p_cust_id NUMBER, p_card_type VARCHAR2, p_card_no
SYSTOOLS
VARCHAR2)
IS
v_card_info typ_cr_card_nst;
i INTEGER;
BEGIN
SELECT credit_cards
INTO v_card_info
FROM customers
WHERE customer_id = p_cust_id;
IF v_card_info.EXISTS(1) THEN -- cards exist, add more
i := v_card_info.LAST;
v_card_info.EXTEND(1);
v_card_info(i+1) := typ_cr_card(p_card_type, p_card_no);
UPDATE customers
SET credit_cards = v_card_info
SYSTOOLS
SET credit_cards = typ_cr_card_nst
(typ_cr_card(p_card_type, p_card_no))
WHERE customer_id = p_cust_id;
END IF;
END update_card_info;
PROCEDURE display_card_info
(p_cust_id NUMBER)
IS
v_card_info typ_cr_card_nst;
i INTEGER;
BEGIN
SELECT credit_cards
INTO v_card_info
FROM customers
WHERE customer_id = p_cust_id;
SYSTOOLS
IF v_card_info.EXISTS(1) THEN
FOR idx IN v_card_info.FIRST..v_card_info.LAST LOOP
DBMS_OUTPUT.PUT('Card Type: ' ||
v_card_info(idx).card_type || ' ');
DBMS_OUTPUT.PUT_LINE('/ Card No: ' ||
v_card_info(idx).card_num );
END LOOP;
ELSE
DBMS_OUTPUT.PUT_LINE('Customer has no credit cards.');
END IF;
END display_card_info;
END credit_card_pkg; -- package body
/
6) Test your package with the following statements and compare the output:
SYSTOOLS
EXECUTE credit_card_pkg.display_card_info(120)
Customer has no credit cards.
PL/SQL procedure successfully completed.
EXECUTE credit_card_pkg.update_card_info –
(120, 'Visa', 11111111)
PL/SQL procedure successfully completed.
SELECT credit_cards
FROM customers
WHERE customer_id = 120;
CREDIT_CARDS(CARD_TYPE, CARD_NUM)
SYSTOOLS
EXECUTE credit_card_pkg.display_card_info(120)
Card Type: Visa / Card No: 11111111
PL/SQL procedure successfully completed.
EXECUTE credit_card_pkg.update_card_info –
(120, 'MC', 2323232323)
PL/SQL procedure successfully completed.
EXECUTE credit_card_pkg.update_card_info –
(120, 'DC', 4444444)
PL/SQL procedure successfully completed.
EXECUTE credit_card_pkg.display_card_info(120)
Card Type: Visa / Card No: 11111111
Card Type: MC / Card No: 2323232323
Card Type: DC / Card No: 4444444
PL/SQL procedure successfully completed.
SYSTOOLS
SET SERVEROUT ON
EXECUTE credit_card_pkg.display_card_info(120)
SELECT credit_cards
FROM customers
WHERE customer_id = 120;
EXECUTE credit_card_pkg.display_card_info(120)
SYSTOOLS
2323232323)
EXECUTE credit_card_pkg.display_card_info(120)
7) Write a SELECT statement against the credit_cards column to unnest the data.
Use the TABLE expression. Use SQL*Plus.
SELECT credit_cards
FROM customers
CREDIT_CARDS(CARD_TYPE, CARD_NUM)
SYSTOOLS
--------------------------------------------------------
TYP_CR_CARD_NST(TYP_CR_CARD('Visa', 11111111),
TYP_CR_CARD('MC', 2323232323), TYP_CR_CARD('DC', 4444444))
then rewrite it using the TABLE expression so that the results look like this:
SYSTOOLS
WHERE customer_id = 120;
SYSTOOLS
SYSTOOLS
Practice 5-1: Using Advanced Interface Methods
Using External C Routines
An external C routine definition is created for you. The .c file is stored in the
D:\labs\labs directory. This function returns the tax amount based on the total sales
figure that is passed to the function as a parameter. The.c file is named calc_tax.c.
SYSTOOLS
tax = (n*8)/100;
return (tax);
}
1) A DLL file called calc_tax.dll was created for you. Copy the file from the
D:\labs\labs directory into your
D:\app\Administrator\product\11.1.0\db_1\BIN directory:
In Explorer, right click the calc_tax.dll file and select Copy from the
submenu.
SYSTOOLS
In Explorer, navigate to the
D:\app\Administrator\product\11.1.0\db_1\BIN folder. Right-click
SYSTOOLS
SYSTOOLS
2) As the SYS user, create the alias library object. Name the library object c_code and
define its path as:
connect / as sysdba
3) Grant execute privilege on the library to the OE user by executing the following
command:
GRANT EXECUTE ON c_code TO OE;
SYSTOOLS
4) Publish the external C routine.
As the OE user, create a function named call_c. This function has one numeric
parameter and it returns a binary integer. Identify the AS LANGUAGE, LIBRARY,
and NAME clauses of the function.
CONNECT oe
SYSTOOLS
DBMS_OUTPUT.PUT_LINE statement so that you can view the results returned
from your C function.
CREATE OR REPLACE PROCEDURE c_output
(p_in IN BINARY_INTEGER)
IS
i BINARY_INTEGER;
BEGIN
i := call_c(p_in);
DBMS_OUTPUT.PUT_LINE('The total tax is: ' || i);
END c_output;
/
SET SERVEROUT ON
SYSTOOLS
EXECUTE c_output(1000000)
A Java method definition is created for you. The method accepts a 16-digit credit card
number as the argument and returns the formatted credit card number (4 digits followed
by a space). The name of the .class file is FormatCreditCardNo.class. The
method is defined as:
SYSTOOLS
{
int count=0, space=0;
String oldcc=cardno[0];
String[] newcc= {""};
while (count<16)
{
newcc[0]+= oldcc.charAt(count);
space++;
if (space ==4)
{ newcc[0]+=" "; space=0; }
count++;
}
cardno[0]=newcc [0];
}
}
SYSTOOLS
8) Publish the Java class method by defining a PL/SQL procedure named CCFORMAT.
This procedure accepts one IN OUT parameter.
SYSTOOLS
NAME 'FormatCreditCardNo.formatCard(java.lang.String[])';
/
9) Execute the Java class method. Define one SQL*Plus or Oracle SQL Developer
variable, initialize it, and use the EXECUTE command to execute the CCFORMAT
procedure. Your output should match the PRINT output shown below.
EXECUTE ccformat(:x);
PRINT x
X
-------------------
1234 5678 1234 5678
VARIABLE x VARCHAR2(20)
EXECUTE :x := '1234567887654321'
SYSTOOLS
EXECUTE ccformat(:x)
PRINT x
SYSTOOLS
Practice 6-1: Implementing Fine-Grained Access Control for VPD
In this practice, you define an application context and security policy to implement the
policy: “Sales representatives can see their own order information only in the ORDERS
table.” You create sales representative IDs to test the success of your implementation.
Examine the definition of the ORDERS table and the ORDER count for each sales
representative:
1) Use your OE connection.
Examine and then run the lab_06_01.sql script. This script creates the ID
accounts of sales representatives with appropriate privileges to access the database:
SYSTOOLS
DEFAULT TABLESPACE USERS
TEMPORARY TABLESPACE TEMP
QUOTA UNLIMITED ON USERS;
SYSTOOLS
QUOTA UNLIMITED ON USERS;
SYSTOOLS
CREATE USER sr161 IDENTIFIED BY oracle
DEFAULT TABLESPACE USERS
TEMPORARY TABLESPACE TEMP
QUOTA UNLIMITED ON USERS;
SYSTOOLS
oe.orders TO sr153, sr154, sr155, sr156, sr158,
sr159, sr160, sr161, sr163;
CONNECT oe/oe
@lab_06_01.sql
SYSTOOLS
2) Set up an application context:
a) Connect to the database as SYSDBA before creating this context.
b) Create an application context named sales_orders_ctx.
c) Associate this context with the oe.sales_orders_pkg.
CONNECT /AS sysdba
SYSTOOLS
3) Connect as OE.
a) Examine this package specification:
CREATE OR REPLACE PACKAGE sales_orders_pkg
IS
PROCEDURE set_app_context;
FUNCTION the_predicate
(p_schema VARCHAR2, p_name VARCHAR2)
RETURN VARCHAR2;
END sales_orders_pkg; -- package spec
/
b) Create this package specification, and then the package body in the OE schema.
SYSTOOLS
c) When you create the package body, set up two constants as follows:
c_context CONSTANT VARCHAR2(30) := 'SALES_ORDERS_CTX';
c_attrib CONSTANT VARCHAR2(30) := 'SALES_REP';
PROCEDURE set_app_context
IS
v_user VARCHAR2(30);
BEGIN
SELECT user INTO v_user FROM dual;
SYSTOOLS
DBMS_SESSION.SET_CONTEXT
(c_context, c_attrib, v_user);
END set_app_context;
FUNCTION the_predicate
(p_schema VARCHAR2, p_name VARCHAR2)
RETURN VARCHAR2
IS
v_context_value VARCHAR2(100) :=
SYS_CONTEXT(c_context, c_attrib);
v_restriction VARCHAR2(2000);
BEGIN
IF v_context_value LIKE 'SR%' THEN
v_restriction :=
'SALES_REP_ID =
SYSTOOLS
v_restriction := null;
END IF;
RETURN v_restriction;
END the_predicate;
SYSTOOLS
policy_name OE_ORDERS_ACCESS_POLICY
function_schema OE
policy_function SALES_ORDERS_PKG.THE_PREDICATE
statement_types SELECT, INSERT, UPDATE, DELETE
update_check FALSE,
enable TRUE
DECLARE
BEGIN
DBMS_RLS.ADD_POLICY (
'OE',
'ORDERS',
'OE_ORDERS_ACCESS_POLICY',
'OE',
SYSTOOLS
'SALES_ORDERS_PKG.THE_PREDICATE',
'SELECT, INSERT, UPDATE, DELETE',
FALSE,
TRUE);
END;
/
5) Connect as SYSDBA and create a logon trigger to implement the fine-grained access
control. You can call the SET_ID_ON_LOGON trigger. This trigger causes the
context to be set as each user is logged on.
CONNECT /as sysdba
SYSTOOLS
BEGIN
oe.sales_orders_pkg.set_app_context;
END;
/
6) Test the fine-grained access implementation. Connect as your SR user and query the
ORDERS table. For example, your results should match the following:
CONNECT sr153/oracle
SALES_REP_ID COUNT(*)
SYSTOOLS
------------ ----------
153 5
CONNECT sr154/oracle
SALES_REP_ID COUNT(*)
------------ ----------
154 10
Notes
SYSTOOLS
During debugging, you may need to disable or remove some of the objects created for
this lesson.
If you need to disable the logon trigger, issue the following command:
If you need to remove the policy that you created, issue the following command:
EXECUTE DBMS_RLS.DROP_POLICY('OE', 'ORDERS',-
'OE_ORDERS_ACCESS_POLICY')
SYSTOOLS
Practice 7-1: Manipulating Large Objects
Working with LOBs
In this practice, you create a table with both BLOB and CLOB columns. Then, you use the
DBMS_LOB package to populate the table and manipulate the data.
SYSTOOLS
REVIEW CLOB N/A
PICTURE BLOB N/A
@D:\labs\labs\lab_07_01.sql
2) Insert two rows into the PERSONNEL table, one each for employee 2034 (whose last
name is Allen) and employee 2035 (whose last name is Bond). Use the empty
function for the CLOB, and provide NULL as the value for the BLOB.
SYSTOOLS
INSERT INTO personnel
VALUES (2034, 'Allen', empty_clob(), NULL);
SYSTOOLS
review details for two employees.
CREATE TABLE review_table (
employee_id number,
ann_review VARCHAR2(2000));
COMMIT;
SYSTOOLS
@D:\labs\labs\lab_07_03.sql
UPDATE personnel
SET review = (SELECT ann_review
FROM review_table
WHERE employee_id = 2034)
SYSTOOLS
WHERE last_name = 'Allen';
b) Populate the CLOB for the second row by using PL/SQL and the DBMS_LOB
package. Use this SELECT statement to provide a value for the LOB locator:
SELECT ann_review
FROM review_table
WHERE employee_id = 2035;
UPDATE personnel
SET review = (SELECT ann_review
FROM review_table
WHERE employee_id = 2035)
WHERE last_name = 'Bond';
5) Create a procedure that adds a locator to a binary file to the PICTURE column of
SYSTOOLS
the PRODUCT_INFORMATION table. The binary file is a picture of the Product.
The image files are named after the Product IDs. You need to load an image file
locator into all rows in the Printers category (CATEGORY_ID = 12) in the
PRODUCT_INFORMATION table.
a) Create a DIRECTORY object called PRODUCT_PIC that references the
location of the binary file. These files are available in the
D:\labs\labs\DATA_FILES\PRODUCT_PIC folder.
CREATE DIRECTORY product_pic AS
'D:\labs\labs\DEMO_FILES\PRODUCT_PIC';
(Alternatively, use the D:\labs\labs\lab_07_05a.sql script.)
b) Add the image column to the PRODUCT_INFORMATION table by using:
ALTER TABLE product_information ADD (picture BFILE);
(Alternatively, use the D:\labs\labs\lab_07_05_b.sql file.)
SYSTOOLS
c) Create a PL/SQL procedure called load_product_image that uses
DBMS_LOB.FILEEXISTS to test whether the product picture file exists. If
the file exists, set the BFILE locator for the file in the PICTURE column;
otherwise, display a message that the file does not exist. Use the
DBMS_OUTPUT package to report file size information for each image
associated with the PICTURE column.
(Alternatively, use the D:\labs\labs\lab_07_05_c.sql file)
CREATE OR REPLACE PROCEDURE load_product_image
(p_dir IN VARCHAR2)
IS
v_file BFILE;
v_filename VARCHAR2(40);
v_rec_number NUMBER;
v_file_exists BOOLEAN;
CURSOR product_csr IS
SYSTOOLS
SELECT product_id
FROM product_information
WHERE category_id = 12
FOR UPDATE;
BEGIN
DBMS_OUTPUT.PUT_LINE('LOADING LOCATORS TO IMAGES...');
FOR rec IN product_csr
LOOP
v_filename := rec.product_id || '.gif';
v_file := BFILENAME(p_dir, v_filename);
v_file_exists := (DBMS_LOB.FILEEXISTS(v_file) = 1);
IF v_file_exists THEN
DBMS_LOB.FILEOPEN(v_file);
UPDATE product_information
SET picture = v_file
SYSTOOLS
|| ' Size: ' || DBMS_LOB.GETLENGTH(v_file));
DBMS_LOB.FILECLOSE(v_file);
v_rec_number := product_csr%ROWCOUNT;
ELSE
DBMS_OUTPUT.PUT_LINE('File ' || v_filename ||
' does not exist');
END IF;
END LOOP;
DBMS_OUTPUT.PUT_LINE('TOTAL FILES UPDATED: ' ||
v_rec_number);
EXCEPTION
WHEN OTHERS THEN
DBMS_LOB.FILECLOSE(v_file);
DBMS_OUTPUT.PUT_LINE('Error: '|| to_char(SQLCODE) ||
SQLERRM);
END load_product_image;
/
SYSTOOLS
d) Invoke the procedure by passing the name of the directory object
PRODUCT_PIC as a string literal parameter value.
SET SERVEROUTPUT ON
EXECUTE load_product_image('PRODUCT_PIC');
e) Check the LOB space usage of the PRODUCT_INFORMATION table. Use the
SYSTOOLS
D:\labs\labs\lab_07_05_e.sql file to create the procedure and
execute it.
CREATE OR REPLACE PROCEDURE check_space
IS
l_fs1_bytes NUMBER;
l_fs2_bytes NUMBER;
l_fs3_bytes NUMBER;
l_fs4_bytes NUMBER;
l_fs1_blocks NUMBER;
l_fs2_blocks NUMBER;
l_fs3_blocks NUMBER;
l_fs4_blocks NUMBER;
l_full_bytes NUMBER;
l_full_blocks NUMBER;
SYSTOOLS
DBMS_SPACE.SPACE_USAGE(
segment_owner => 'OE',
segment_name => 'PRODUCT_INFORMATION',
segment_type => 'TABLE',
fs1_bytes => l_fs1_bytes,
fs1_blocks => l_fs1_blocks,
fs2_bytes => l_fs2_bytes,
fs2_blocks => l_fs2_blocks,
fs3_bytes => l_fs3_bytes,
fs3_blocks => l_fs3_blocks,
fs4_bytes => l_fs4_bytes,
fs4_blocks => l_fs4_blocks,
full_bytes => l_full_bytes,
full_blocks => l_full_blocks,
unformatted_blocks => l_unformatted_blocks,
unformatted_bytes => l_unformatted_bytes
);
SYSTOOLS
DBMS_OUTPUT.ENABLE;
DBMS_OUTPUT.PUT_LINE(' FS1 Blocks = '||l_fs1_blocks||'
Bytes = '||l_fs1_bytes);
DBMS_OUTPUT.PUT_LINE(' FS2 Blocks = '||l_fs2_blocks||'
Bytes = '||l_fs2_bytes);
DBMS_OUTPUT.PUT_LINE(' FS3 Blocks = '||l_fs3_blocks||'
Bytes = '||l_fs3_bytes);
DBMS_OUTPUT.PUT_LINE(' FS4 Blocks = '||l_fs4_blocks||'
Bytes = '||l_fs4_bytes);
DBMS_OUTPUT.PUT_LINE('Full Blocks = '||l_full_blocks||'
Bytes = '||l_full_bytes);
DBMS_OUTPUT.PUT_LINE('================================');
DBMS_OUTPUT.PUT_LINE('Total Blocks =
'||to_char(l_fs1_blocks + l_fs2_blocks +
l_fs3_blocks + l_fs4_blocks + l_full_blocks)|| ' ||
Total Bytes = '|| to_char(l_fs1_bytes + l_fs2_bytes
SYSTOOLS
+ l_fs3_bytes + l_fs4_bytes + l_full_bytes));
END;
/
SYSTOOLS
set serveroutput on
execute check_space;
SYSTOOLS
SYSTOOLS
SYSTOOLS
Practice 8-1: Using SecureFile Format LOBs
Working with SecureFile LOBS
In this lesson, you practice using the features of the SecureFile format LOBs.
1) In this practice, you migrate a BasicFile format LOB to a SecureFile format LOB.
You need to set up several supporting structures:
a) As the OE user, drop your existing PRODUCT_DESCRIPTIONS table and
create a new one:
DROP TABLE product_descriptions PURGE;
connect oe
SYSTOOLS
DROP TABLE product_descriptions PURGE;
b) As the SYS user, create a new tablespace to store the LOB information.
CREATE TABLESPACE lob_tbs2
DATAFILE 'lob_tbs2.dbf' SIZE 1500M REUSE
AUTOEXTEND ON NEXT 200M
MAXSIZE 3000M
SEGMENT SPACE MANAGEMENT AUTO;
SYSTOOLS
CREATE TABLESPACE lob_tbs2
DATAFILE 'lob_tbs2.dbf' SIZE 1500M REUSE
AUTOEXTEND ON NEXT 200M
MAXSIZE 3000M
SEGMENT SPACE MANAGEMENT AUTO;
c) Create a directory object that identifies the location of your LOBs. In the
Oracle classroom, the location is in the Oracle
D:\labs\labs\DATA_FILES\PRODUCT_PIC folder. Then, grant read
privileges on the directory to the OE user.
CREATE OR REPLACE DIRECTORY product_files
AS 'd:\Labs\DATA_FILES\PRODUCT_PIC ';
SYSTOOLS
AS 'D:\labs\DATA_FILES\PRODUCT_PIC';
d) As the OE user, alter the table and add a BLOB column of the BASICFILE
storage type.
ALTER TABLE product_descriptions ADD
(detailed_product_info BLOB )
LOB (detailed_product_info) STORE AS BASICFILE
(tablespace lob_tbs2);
connect oe
SYSTOOLS
LOB (detailed_product_info)
STORE AS BASICFILE (tablespace lob_tbs2);
e) Create the procedure to load the LOB data into the column (You can run the
D:\labs\labs\lab_08_01_e.sql script):
CREATE OR REPLACE PROCEDURE loadLOBFromBFILE_proc (
p_dest_loc IN OUT BLOB, p_file_name IN VARCHAR2)
IS
v_src_loc BFILE := BFILENAME('PRODUCT_FILES',
p_file_name);
v_amount INTEGER := 4000;
BEGIN
DBMS_LOB.OPEN(v_src_loc, DBMS_LOB.LOB_READONLY);
v_amount := DBMS_LOB.GETLENGTH(v_src_loc);
DBMS_LOB.LOADFROMFILE(p_dest_loc, v_src_loc, v_amount);
SYSTOOLS
DBMS_LOB.CLOSE(v_src_loc);
END loadLOBFromBFILE_proc;
/
connect oe
SYSTOOLS
/
f) As the OE user, create the procedure to write the LOB data (You can run the
D:\labs\labs\lab_08_01_f.sql script):
CREATE OR REPLACE PROCEDURE write_lob (p_file IN
VARCHAR2)
IS
i NUMBER; v_id NUMBER; v_b BLOB;
BEGIN
DBMS_OUTPUT.ENABLE;
DBMS_OUTPUT.PUT_LINE('Begin inserting rows...');
FOR i IN 1 .. 5 LOOP
v_id:=SUBSTR(p_file, 1, 4);
INSERT INTO product_descriptions
VALUES (v_id, EMPTY_BLOB())
RETURNING detailed_product_info INTO v_b;
SYSTOOLS
loadLOBFromBFILE_proc(v_b,p_file);
DBMS_OUTPUT.PUT_LINE('Row '|| i ||' inserted.');
END LOOP;
COMMIT;
END write_lob;
/
connect oe
SYSTOOLS
VALUES (v_id, EMPTY_BLOB())
RETURNING detailed_product_info INTO v_b;
loadLOBFromBFILE_proc(v_b,p_file);
DBMS_OUTPUT.PUT_LINE('Row '|| i ||' inserted.');
END LOOP;
COMMIT;
END write_lob;
/
SYSTOOLS
Note: If you are using Oracle SQL Developer, issue only the EXECUTE
statements listed as follows. In Oracle SQL Developer, some of the
SQL*Plus commands are ignored. It is recommended that you use SQL*Plus
for this exercise.
set serveroutput on
set verify on
set term on
set lines 200
timing start load_data
execute write_lob('1726_LCD.doc');
execute write_lob('1734_RS232.doc');
execute write_lob('1739_SDRAM.doc');
timing stop
connect oe
SYSTOOLS
set serveroutput on
set verify on
set term on
set lines 200
timing start load_data
execute write_lob('1726_LCD.doc');
execute write_lob('1734_RS232.doc');
execute write_lob('1739_SDRAM.doc');
timing stop
SYSTOOLS
SYSTOOLS
SYSTOOLS
h) As the SYSTEM user, check the segment type in the data dictionary.
SELECT segment_name, segment_type, segment_subtype
FROM dba_segments
WHERE tablespace_name = 'LOB_TBS2'
AND segment_type = 'LOBSEGMENT';
FROM
SYSTOOLS
connect /as sysdba
SELECT
WHERE
segment_name, segment_type, segment_subtype
dba_segments
tablespace_name = 'LOB_TBS2'
AND segment_type = 'LOBSEGMENT';
SYSTOOLS
(product_id NUMBER,
detailed_product_info BLOB)
LOB(detailed_product_info) STORE AS SECUREFILE
(TABLESPACE lob_tbs2);
connect oe
j) Connect as the SYSTEM user and run the redefinition script. (You can run the
D:\labs\lab\lab_08_01_j.sql script.)
SYSTOOLS
DECLARE
error_count PLS_INTEGER := 0;
BEGIN
DBMS_REDEFINITION.START_REDEF_TABLE
('OE', 'product_descriptions',
'product_descriptions_interim',
'product_id product_id, detailed_product_info
detailed_product_info',
OPTIONS_FLAG => DBMS_REDEFINITION.CONS_USE_ROWID);
DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS
('OE', 'product_descriptions',
'product_descriptions_interim',
1, true,true,true,false, error_count);
DBMS_OUTPUT.PUT_LINE('Errors := ' ||
TO_CHAR(error_count));
DBMS_REDEFINITION.FINISH_REDEF_TABLE
SYSTOOLS
('OE', 'product_descriptions',
'product_descriptions_interim');
END;
/
DECLARE
error_count PLS_INTEGER := 0;
BEGIN
DBMS_REDEFINITION.START_REDEF_TABLE
('OE', 'product_descriptions',
'product_descriptions_interim',
'product_id product_id, detailed_product_info
SYSTOOLS
('OE', 'product_descriptions',
'product_descriptions_interim',
1, true,true,true,false, error_count);
DBMS_OUTPUT.PUT_LINE('Errors := ' ||
TO_CHAR(error_count));
DBMS_REDEFINITION.FINISH_REDEF_TABLE
('OE', 'product_descriptions',
'product_descriptions_interim');
END;
/
SYSTOOLS
connect oe
l) As the SYS user, check the segment type in the data dictionary to make sure it
is now set to SECUREFILE.
SELECT segment_name, segment_type, segment_subtype
FROM dba_segments
WHERE tablespace_name = 'LOB_TBS2'
AND segment_type = 'LOBSEGMENT';
SYSTOOLS
WHERE tablespace_name = 'LOB_TBS2'
AND segment_type = 'LOBSEGMENT';
m) As the OE user, check the space of the table by executing the CHECK_SPACE
procedure. (You can run the D:\labs\labs\lab_08_01_m.sql script.)
CREATE OR REPLACE PROCEDURE check_space
SYSTOOLS
l_fs3_bytes NUMBER;
l_fs4_bytes NUMBER;
l_fs1_blocks NUMBER;
l_fs2_blocks NUMBER;
l_fs3_blocks NUMBER;
l_fs4_blocks NUMBER;
l_full_bytes NUMBER;
l_full_blocks NUMBER;
l_unformatted_bytes NUMBER;
l_unformatted_blocks NUMBER;
BEGIN
DBMS_SPACE.SPACE_USAGE(
segment_owner => 'OE',
segment_name => 'PRODUCT_DESCRIPTIONS',
segment_type => 'TABLE',
fs1_bytes => l_fs1_bytes,
fs1_blocks => l_fs1_blocks,
SYSTOOLS
fs2_bytes => l_fs2_bytes,
fs2_blocks => l_fs2_blocks,
fs3_bytes => l_fs3_bytes,
fs3_blocks => l_fs3_blocks,
fs4_bytes => l_fs4_bytes,
fs4_blocks => l_fs4_blocks,
full_bytes => l_full_bytes,
full_blocks => l_full_blocks,
unformatted_blocks => l_unformatted_blocks,
unformatted_bytes => l_unformatted_bytes
);
DBMS_OUTPUT.ENABLE;
DBMS_OUTPUT.PUT_LINE(' FS1 Blocks = '||l_fs1_blocks||'
Bytes = '||l_fs1_bytes);
DBMS_OUTPUT.PUT_LINE(' FS2 Blocks = '||l_fs2_blocks||'
Bytes = '||l_fs2_bytes);
DBMS_OUTPUT.PUT_LINE(' FS3 Blocks = '||l_fs3_blocks||'
SYSTOOLS
Bytes = '||l_fs3_bytes);
DBMS_OUTPUT.PUT_LINE(' FS4 Blocks = '||l_fs4_blocks||'
Bytes = '||l_fs4_bytes);
DBMS_OUTPUT.PUT_LINE('Full Blocks = '||l_full_blocks||'
Bytes = '||l_full_bytes);
DBMS_OUTPUT.PUT_LINE('===================================
=========');
DBMS_OUTPUT.PUT_LINE('Total Blocks =
'||to_char(l_fs1_blocks + l_fs2_blocks +
l_fs3_blocks + l_fs4_blocks + l_full_blocks)|| ' ||
Total Bytes = '|| to_char(l_fs1_bytes + l_fs2_bytes
+ l_fs3_bytes + l_fs4_bytes + l_full_bytes));
END;
/
SYSTOOLS
SYSTOOLS
SYSTOOLS
SYSTOOLS
Practice 9-1: Performance and Tuning
In this practice, you measure and examine performance and tuning.
SYSTOOLS
PROCEDURE display_card_info
(p_cust_id NUMBER);
END credit_card_pkg; -- package spec
/
CREATE OR REPLACE PACKAGE BODY credit_card_pkg
IS
PROCEDURE update_card_info
(p_cust_id NUMBER, p_card_type VARCHAR2,
p_card_no VARCHAR2)
IS
v_card_info typ_cr_card_nst;
i INTEGER;
BEGIN
SELECT credit_cards
INTO v_card_info
FROM customers
SYSTOOLS
WHERE customer_id = p_cust_id;
IF v_card_info.EXISTS(1) THEN -- cards exist, add more
i := v_card_info.LAST;
v_card_info.EXTEND(1);
v_card_info(i+1) := typ_cr_card(p_card_type,
p_card_no);
UPDATE customers
SET credit_cards = v_card_info
WHERE customer_id = p_cust_id;
ELSE -- no cards for this customer yet, construct one
UPDATE customers
SET credit_cards = typ_cr_card_nst
(typ_cr_card(p_card_type, p_card_no))
WHERE customer_id = p_cust_id;
END IF;
IS
SYSTOOLS
PROCEDURE display_card_info
(p_cust_id NUMBER)
v_card_info typ_cr_card_nst;
i INTEGER;
BEGIN
SELECT credit_cards
INTO v_card_info
FROM customers
WHERE customer_id = p_cust_id;
IF v_card_info.EXISTS(1) THEN
FOR idx IN v_card_info.FIRST..v_card_info.LAST LOOP
DBMS_OUTPUT.PUT('Card Type: ' ||
v_card_info(idx).card_type || ' ');
SYSTOOLS
DBMS_OUTPUT.PUT_LINE('/ Card No: ' ||
v_card_info(idx).card_num );
END LOOP;
ELSE
DBMS_OUTPUT.PUT_LINE('Customer has no credit
cards.');
END IF;
END display_card_info;
END credit_card_pkg; -- package body
/
However, this code needs to be improved. The following issues exist in the code:
− The local variables use the INTEGER data type.
− The same SELECT statement is run in the two procedures.
− The same IF v_card_info.EXISTS(1) THEN statement is in the two
procedures.
SYSTOOLS
Using Efficient Data Types
2) To improve the code, make the following modifications:
a) Change the local INTEGER variables to use a more efficient data type.
b) Move the duplicated code into a function. The package specification for the
modification is:
CREATE OR REPLACE PACKAGE credit_card_pkg
IS
FUNCTION cust_card_info
(p_cust_id NUMBER, p_card_info IN OUT typ_cr_card_nst )
RETURN BOOLEAN;
SYSTOOLS
PROCEDURE display_card_info
(p_cust_id NUMBER);
SYSTOOLS
IS
FUNCTION cust_card_info
(p_cust_id NUMBER, p_card_info IN OUT typ_cr_card_nst )
RETURN BOOLEAN;
PROCEDURE update_card_info
(p_cust_id NUMBER, p_card_type VARCHAR2,
p_card_no VARCHAR2);
PROCEDURE display_card_info
(p_cust_id NUMBER);
END credit_card_pkg; -- package spec
/
FUNCTION cust_card_info
(p_cust_id NUMBER, p_card_info IN OUT typ_cr_card_nst )
SYSTOOLS
RETURN BOOLEAN
IS
v_card_info_exists BOOLEAN;
BEGIN
SELECT credit_cards
INTO p_card_info
FROM customers
WHERE customer_id = p_cust_id;
IF p_card_info.EXISTS(1) THEN
v_card_info_exists := TRUE;
ELSE
v_card_info_exists := FALSE;
END IF;
RETURN v_card_info_exists;
END cust_card_info;
SYSTOOLS
p_card_no VARCHAR2)
IS
v_card_info typ_cr_card_nst;
i PLS_INTEGER;
BEGIN
IF cust_card_info(p_cust_id, v_card_info) THEN
-- cards exist, add more
i := v_card_info.LAST;
v_card_info.EXTEND(1);
v_card_info(i+1) := typ_cr_card(p_card_type, p_card_no);
UPDATE customers
SET credit_cards = v_card_info
WHERE customer_id = p_cust_id;
ELSE -- no cards for this customer yet, construct one
UPDATE customers
SET credit_cards = typ_cr_card_nst
(typ_cr_card(p_card_type, p_card_no))
SYSTOOLS
WHERE customer_id = p_cust_id;
END IF;
END update_card_info;
PROCEDURE display_card_info
(p_cust_id NUMBER)
IS
v_card_info typ_cr_card_nst;
i PLS_INTEGER;
BEGIN
IF cust_card_info(p_cust_id, v_card_info) THEN
FOR idx IN v_card_info.FIRST..v_card_info.LAST LOOP
DBMS_OUTPUT.PUT('Card Type: ' ||
v_card_info(idx).card_type || ' ');
DBMS_OUTPUT.PUT_LINE('/ Card No: ' ||
v_card_info(idx).card_num );
END LOOP;
SYSTOOLS
ELSE
DBMS_OUTPUT.PUT_LINE('Customer has no credit cards.');
END IF;
END display_card_info;
END credit_card_pkg; -- package body
/
3) Test your modified code with the following data:
EXECUTE credit_card_pkg.update_card_info –
(120, 'AM EX', 55555555555)
PL/SQL procedure successfully completed.
EXECUTE credit_card_pkg.display_card_info(120)
Card Type: Visa / Card No: 11111111
Card Type: MC / Card No: 2323232323
SYSTOOLS
PL/SQL procedure successfully completed.
EXECUTE credit_card_pkg.display_card_info(120)
Card Type: AM EX / Card No: 55555555555
SYSTOOLS
previous question #2.
b) Modify the code to use the RETURNING clause to find information about the
rows that are affected by the UPDATE statements.
CREATE OR REPLACE PACKAGE credit_card_pkg
IS
FUNCTION cust_card_info
(p_cust_id NUMBER, p_card_info IN OUT typ_cr_card_nst )
RETURN BOOLEAN;
PROCEDURE update_card_info
(p_cust_id NUMBER, p_card_type VARCHAR2,
p_card_no VARCHAR2, o_card_info OUT typ_cr_card_nst);
PROCEDURE display_card_info
(p_cust_id NUMBER);
END credit_card_pkg; -- package spec
/
SYSTOOLS
CREATE OR REPLACE PACKAGE BODY credit_card_pkg
IS
FUNCTION cust_card_info
(p_cust_id NUMBER, p_card_info IN OUT typ_cr_card_nst )
RETURN BOOLEAN
IS
v_card_info_exists BOOLEAN;
BEGIN
SELECT credit_cards
INTO p_card_info
FROM customers
WHERE customer_id = p_cust_id;
IF p_card_info.EXISTS(1) THEN
v_card_info_exists := TRUE;
SYSTOOLS
RETURN v_card_info_exists;
END cust_card_info;
PROCEDURE update_card_info
(p_cust_id NUMBER, p_card_type VARCHAR2,
p_card_no VARCHAR2, o_card_info OUT typ_cr_card_nst)
IS
v_card_info typ_cr_card_nst;
i PLS_INTEGER;
BEGIN
SYSTOOLS
SET credit_cards = v_card_info
WHERE customer_id = p_cust_id
RETURNING credit_cards INTO o_card_info;
ELSE -- no cards for this customer yet, construct one
UPDATE customers
SET credit_cards = typ_cr_card_nst
(typ_cr_card(p_card_type, p_card_no))
WHERE customer_id = p_cust_id
RETURNING credit_cards INTO o_card_info;
END IF;
END update_card_info;
PROCEDURE display_card_info
(p_cust_id NUMBER)
IS
v_card_info typ_cr_card_nst;
i PLS_INTEGER;
SYSTOOLS
BEGIN
IF cust_card_info(p_cust_id, v_card_info) THEN
FOR idx IN v_card_info.FIRST..v_card_info.LAST LOOP
DBMS_OUTPUT.PUT('Card Type: ' ||
v_card_info(idx).card_type || ' ');
DBMS_OUTPUT.PUT_LINE('/ Card No: ' ||
v_card_info(idx).card_num );
END LOOP;
ELSE
DBMS_OUTPUT.PUT_LINE('Customer has no credit cards.');
END IF;
END display_card_info;
END credit_card_pkg; -- package body
/
SYSTOOLS
CREATE OR REPLACE PROCEDURE test_credit_update_info
(p_cust_id NUMBER, p_card_type VARCHAR2, p_card_no NUMBER)
IS
v_card_info typ_cr_card_nst;
BEGIN
credit_card_pkg.update_card_info
(p_cust_id, p_card_type, p_card_no, v_card_info);
END test_credit_update_info;
/
-- execute this code:
CREATE OR REPLACE PROCEDURE test_credit_update_info
(p_cust_id NUMBER, p_card_type VARCHAR2, p_card_no NUMBER)
IS
v_card_info typ_cr_card_nst;
BEGIN
credit_card_pkg.update_card_info
(p_cust_id, p_card_type, p_card_no, v_card_info);
SYSTOOLS
END test_credit_update_info;
/
SYSTOOLS
5) In this exercise, you test exception handling with the SAVE EXCEPTIONS clause.
a) Run the lab_09_05_a.sql file to create a test table:
CREATE TABLE card_table
(accepted_cards VARCHAR2(50) NOT NULL);
SYSTOOLS
FORALL j IN v_cards.first..v_cards.last
SAVE EXCEPTIONS
EXECUTE IMMEDIATE
'insert into card_table (accepted_cards) values
( :the_card)'
USING v_cards(j);
/
END;
/
c) Note the output:
Note the output: This returns an “Error in Array DML (at line 11),” which is
not very informative. The cause of this error: One or more rows failed in the
DML.
SYSTOOLS
d) Open the lab_09_05_d.sql file and run the contents:
DECLARE
type typ_cards is table of VARCHAR2(50);
v_cards typ_cards := typ_cards
( 'Citigroup Visa', 'Nationscard MasterCard',
'Federal American Express', 'Citizens Visa',
'International Discoverer', 'United Diners Club' );
bulk_errors EXCEPTION;
PRAGMA exception_init (bulk_errors, -24381 );
BEGIN
v_cards.Delete(3);
v_cards.DELETE(6);
FORALL j IN v_cards.first..v_cards.last
SAVE EXCEPTIONS
EXECUTE IMMEDIATE
SYSTOOLS
'insert into card_table (accepted_cards) values (
:the_card)'
USING v_cards(j);
EXCEPTION
WHEN bulk_errors THEN
FOR j IN 1..sql%bulk_exceptions.count
LOOP
Dbms_Output.Put_Line (
TO_CHAR( sql%bulk_exceptions(j).error_index ) || ':
' || SQLERRM(-sql%bulk_exceptions(j).error_code) );
END LOOP;
END;
/
SYSTOOLS
f) Why is the output different?
The PL/SQL block raises the exception 22160 when it encounters an array
element that was deleted. The exception is handled and the block is
completed successfully.
6) In this exercise, you compare the performance between the PLS_INTEGER and
SIMPLE_INTEGER data types with native compilation:
a) Run the lab_09_06_a.sql file to create a testing procedure that contains
conditional compilation:
CREATE OR REPLACE PROCEDURE p
SYSTOOLS
IS
t0 NUMBER :=0;
t1 NUMBER :=0;
two
lmt
BEGIN
SYSTOOLSCONSTANT My_Integer_t := 2;
CONSTANT My_Integer_t := 100000000;
t0 := DBMS_UTILITY.GET_CPU_TIME();
WHILE v01 < lmt LOOP
v00 := v00 + Two;
v01 := v01 + Two;
v02 := v02 + Two;
v03 := v03 + Two;
v04 := v04 + Two;
v05 := v05 + Two;
END LOOP;
SYSTOOLS
t1 := DBMS_UTILITY.GET_CPU_TIME();
DBMS_OUTPUT.PUT_LINE(
RPAD(LOWER($$PLSQL_Code_Type), 15)||
RPAD(LOWER(My_Integer_t_Name), 15)||
TO_CHAR((t1-t0), '9999')||' centiseconds');
END p;
/
b) Open the lab_09_06_b.sql file and run the contents:
ALTER PROCEDURE p COMPILE
PLSQL_Code_Type = NATIVE PLSQL_CCFlags = 'simple:true'
REUSE SETTINGS;
EXECUTE p()
SYSTOOLS
PLSQL_Code_Type = native PLSQL_CCFlags = 'simple:false'
REUSE SETTINGS;
EXECUTE p()
Second run:
SYSTOOLS
SYSTOOLS
Practice 10-1: Improving Performance with Caching
In this practice, you examine the Explain Plan for a query, add the RESULT_CACHE hint
to the query, and reexamine the Explain Plan results. You also execute some code and
modify the code so that PL/SQL result caching is turned on.
SYSTOOLS
Examine the Explain Plan results.
SYSTOOLS
In the SQL Worksheet, paste the code found in the lab_10_01.sql file:
SELECT count(*),
round(avg(quantity_on_hand)) AVG_AMT,
product_id, product_name
FROM inventories natural join product_information
GROUP BY product_id, product_name;
Click the Execute Explain Plan button on the toolbar and observe the results in
the lower region:
SYSTOOLS
SYSTOOLS
Results: SQL caching is not enabled and not visible in the Explain Plan.
2) Add the RESULT_CACHE hint to the query and reexamine the Explain Plan results.
SELECT /*+ result_cache */
count(*),
round(avg(quantity_on_hand)) AVG_AMT,
product_id, product_name
FROM inventories natural join product_information
GROUP BY product_id, product_name;
SYSTOOLS
Examine the Explain Plan results, compared to the previous
Results.
Click the Execute Explain Plan button on the toolbar again, and compare the
results in the lower region with the previous results:
SYSTOOLS
SYSTOOLS
Results: Note that result caching is used in the Explain Plan.
3) The following code is used to generate a list of warehouse names for pick lists in
applications. The WAREHOUSES table is fairly stable and is not modified often.
Click the Run Script button to compile this code (You can use the lab_10_03.sql
file.):
SYSTOOLS
RETURN list_typ
IS
v_count BINARY_INTEGER;
v_wh_names list_typ;
BEGIN
SELECT count(*)
INTO v_count
FROM warehouses;
FOR i in 1..v_count LOOP
SELECT warehouse_name
INTO v_wh_names(i)
FROM warehouses;
END LOOP;
RETURN v_wh_names;
END get_warehouse_names;
SYSTOOLS
SYSTOOLS
Paste the lab_10_03.sql script into the “Enter SQL Statement” box. Click the Run
Script button. You have compiled the function without PL/SQL result caching.
4) Because the function is called frequently, and because the content of the data returned
SYSTOOLS
does not frequently change, this code is a good candidate for PL/SQL result caching.
Modify the code so that PL/SQL result caching is turned on. Click the Run Script
button to compile this code again.
SYSTOOLS
SELECT count(*)
INTO v_count
FROM warehouses;
FOR i in 1..v_count LOOP
SELECT warehouse_name
INTO v_wh_names(i)
FROM warehouses;
END LOOP;
RETURN v_wh_names;
END get_warehouse_names;
SYSTOOLS
SYSTOOLS
SYSTOOLS
Practice 11-1: Analyzing Your Code
In this practice, you use PL/SQL and Oracle SQL Developer to analyze your code.
SYSTOOLS
reference tables or views. (Note: Your results might differ slightly.)
SET SERVEROUT ON
EXECUTE query_code_pkg.encap_compliance
SYSTOOLS
SYSTOOLS
Navigate to the Reports tabbed page in Oracle SQL Developer.
Expand the Data Dictionary Reports node and expand the PL/SQL node.
SYSTOOLS
SYSTOOLS
Select Text search and enter ORDERS for the Value: field. Click the Apply
button.
SYSTOOLS
SYSTOOLS
Using PL/Scope
2) In this practice, you use PL/Scope.
SYSTOOLS
a) Enable your session to collect identifiers.
ALTER SESSION SET PLSCOPE_SETTINGS = 'IDENTIFIERS:ALL';
SYSTOOLS
d) Execute the following statement to create a hierarchical report on the identifier
information on the CREDIT_CARD_PKG code. You can run the
lab_11_02_d.sql script file.
WITH v AS
(SELECT Line,
Col,
INITCAP(NAME) Name,
LOWER(TYPE) Type,
LOWER(USAGE) Usage,
USAGE_ID, USAGE_CONTEXT_ID
FROM USER_IDENTIFIERS
WHERE Object_Name = 'CREDIT_CARD_PKG'
AND Object_Type = 'PACKAGE BODY' )
SELECT RPAD(LPAD(' ', 2*(Level-1)) ||
SYSTOOLS
Name, 20, '.')||' '||
RPAD(Type, 20)|| RPAD(Usage, 20)
IDENTIFIER_USAGE_CONTEXTS
FROM v
START WITH USAGE_CONTEXT_ID = 0
CONNECT BY PRIOR USAGE_ID = USAGE_CONTEXT_ID
ORDER SIBLINGS BY Line, Col;
SYSTOOLS
SYSTOOLS
SYSTOOLS
SYSTOOLS
Using DBMS_METADATA
SYSTOOLS
3) Use DBMS_METADATA to find the metadata for the ORDER_ITEMS table.
a) Create the GET_TABLE_MD function. You can run the lab_11_03_a.sql
script.
CREATE FUNCTION get_table_md RETURN CLOB IS
v_hdl NUMBER; -- returned by 'OPEN'
v_th NUMBER; -- returned by 'ADD_TRANSFORM'
v_doc CLOB;
BEGIN
-- specify the OBJECT TYPE
v_hdl := DBMS_METADATA.OPEN('TABLE');
-- use FILTERS to specify the objects desired
DBMS_METADATA.SET_FILTER(v_hdl ,'SCHEMA','OE');
DBMS_METADATA.SET_FILTER
(v_hdl ,'NAME','ORDER_ITEMS');
-- request to be TRANSFORMED into creation DDL
v_th := DBMS_METADATA.ADD_TRANSFORM(v_hdl,'DDL');
SYSTOOLS
-- FETCH the object
v_doc := DBMS_METADATA.FETCH_CLOB(v_hdl);
-- release resources
DBMS_METADATA.CLOSE(v_hdl);
RETURN v_doc;
END;
/
b) Issue the following statements to view the metadata generated from the
GET_TABLE_MD function:
set pagesize 0
set long 1000000
SYSTOOLS
SYSTOOLS
DBMS_METADATA.GET_XML function. Spool the output to a file named
ORDER_ITEMS_XML.txt in the D:\labs folder.
SPOOL D:\labs\ORDER_ITEMS_XML.txt
SELECT DBMS_METADATA.GET_XML
('TABLE', 'ORDER_ITEMS', 'OE')
FROM dual;
SPOOL OFF
SYSTOOLS
SYSTOOLS
SYSTOOLS
SYSTOOLS
SYSTOOLS
SYSTOOLS
Practice 12-1: Profiling and Tracing
Profiling Data
SYSTOOLS
c) Use DBMS_HPROF.START_PROFILING to start the profiler for your session.
BEGIN
-- start profiling
DBMS_HPROF.START_PROFILING('PROFILE_DATA', 'pd_cc_pkg.txt');
END;
/
SYSTOOLS
credit_card_pkg.update_card_info
(154, 'Discover', '123456789');
END;
/
SYSTOOLS
a) Get the RUN_ID.
SET SERVEROUT ON
DECLARE
v_runid NUMBER;
BEGIN
v_runid := DBMS_HPROF.ANALYZE (LOCATION => 'PROFILE_DATA',
FILENAME => 'pd_cc_pkg.txt');
DBMS_OUTPUT.PUT_LINE('Run ID: ' || v_runid);
END;
/
b) Query the DBMSHP_RUNS table to find top-level information for the RUN_ID
that you retrieved.
SYSTOOLS
SET VERIFY OFF
SYSTOOLS
FROM dbmshp_function_info
WHERE runid = &your_run_id;
SYSTOOLS
SYSTOOLS
(Note: Results are formatted better in Oracle SQL Developer.)
SYSTOOLS
4) Use the plshprof command-line utility to generate simple HTML reports directly
from the raw profiler data.
a) Open a command window.
b) Change the working directory to D:\labs\labs.
c) Run the plshprof utility.
--at your command window, change your working directory to
D:\labs\labs
cd D:\labs\labs
plshprof - output pd_cc_pkg pd_cc_pkg.txt
SYSTOOLS
5) Open the report in your browser and review the data.
In Windows Explorer, navigate to the D:\labs\labs folder.
SYSTOOLS
SYSTOOLS
SYSTOOLS
SYSTOOLS
SYSTOOLS
SYSTOOLS
Practice 13-1: Safeguarding Your Code Against SQL Injection
Attacks
In this practice, you examine PL/SQL code, test it for SQL injection, and rewrite it to
protect against SQL injection vulnerabilities.
2) Code that is most vulnerable to SQL injection attack contains (check all that apply):
SYSTOOLS
Input parameters
3) By default, a stored procedure or SQL method executes with the privileges of the
owner (definer’s rights).
True/False
4) By using AUTHID CURRENT_USER in your code, you are (check all that apply):
SYSTOOLS
⇒ Specifying that the code executes with invoker’s rights
Specifying that the code executes with the highest privilege level
SYSTOOLS
5) Match each attack surface reduction technique to an example of the technique.
Technique Example
Executes code with minimal privileges: Use invoker’s rights
6) Examine this code. Run the lab_13_06.sql script to create the procedure.
CREATE OR REPLACE PROCEDURE get_income_level
(p_email VARCHAR2 DEFAULT NULL)
IS
SYSTOOLS
TYPE cv_custtyp IS REF CURSOR;
cv cv_custtyp;
v_income customers.income_level%TYPE;
v_stmt VARCHAR2(400);
BEGIN
v_stmt := 'SELECT income_level FROM customers WHERE
cust_email = ''' || p_email || '''';
SYSTOOLS
EXCEPTION WHEN OTHERS THEN
dbms_output.PUT_LINE(sqlerrm);
dbms_output.PUT_LINE('SQL statement: ' || v_stmt);
END get_income_level;
/
a) Execute the following statements and note the results.
exec get_income_level('[email protected]')
SYSTOOLS
SYSTOOLS
b) Has SQL injection occurred?
Yes, by using dynamic SQL constructed via concatenation of input values,
you see all users in the database.
Rewriting Code to Protect Against SQL Injection (continued)
7) Rewrite the code to protect against SQL injection. You can run the
lab_13_07.sql script to recreate the procedure.
CREATE OR REPLACE
PROCEDURE get_income_level (p_email VARCHAR2 DEFAULT NULL)
AS
BEGIN
FOR i IN
SYSTOOLS
(SELECT income_level
FROM customers
WHERE cust_email = p_email)
LOOP
DBMS_OUTPUT.PUT_LINE('Income level is:
'||i.income_level);
END LOOP;
END get_income_level;
/
a) Execute the following statements and note the results.
exec get_income_level('[email protected]')
SYSTOOLS
all_users where ''x''=''x')
SYSTOOLS
Start.
SYSTOOLS
SYSTOOLS
SYSTOOLS
SYSTOOLS
Table Descriptions and Data
SYSTOOLS
Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Schema Descriptions
Overall Description
The sample company portrayed by the Oracle Database Sample Schemas operates worldwide to
SYSTOOLS
fulfill orders for several different products. The company has several divisions:
• The Human Resources division tracks information about the employees and facilities of the
company.
• The Order Entry division tracks product inventories and sales of the products of the company
through various channels.
• The Sales History division tracks business statistics to facilitate business decisions.
Each division is represented by a schema. In this course, you have access to the objects in all these
schemas. However, the emphasis of the examples, demonstrations, and practices utilizes the Order
Entry (OE) schema.
All scripts necessary to create the sample schemas reside in the
$ORACLE_HOME/demo/schema/ folder.
SYSTOOLS
SYSTOOLS
SYSTOOLS
clothing, and tools. The company maintains product information that includes product identification
numbers, the category into which the product falls, the weight group (for shipping purposes), the
warranty period if applicable, the supplier, the status of the product, a list price, a minimum price at
which a product will be sold, and a URL for manufacturer information.
Inventory information is also recorded for all products, including the warehouse where the product is
available and the quantity on hand. Because products are sold worldwide, the company maintains the
names of the products and their descriptions in different languages.
The company maintains warehouses in several locations to facilitate filling customer orders. Each
warehouse has a warehouse identification number, name, and location identification number.
Customer information is tracked in some detail. Each customer is assigned an identification number.
Customer records include name, street address, city or province, country, phone numbers (up to five
phone numbers for each customer), and postal code. Some customers order through the Internet, so
email addresses are also recorded. Because of language differences among customers, the company
records the National Language Support (NLS) language and territory of each customer. The company
SYSTOOLS
places a credit limit on its customers to limit the amount for which they can purchase at one time.
Some customers have account managers, whom the company monitors. It keeps track of a customer’s
phone number. These days, you never know how many phone numbers a customer might have, but
you try to keep track of all of them. Because of the language differences of the customers, you
identify the language and territory of each customer.
When a customer places an order, the company tracks the date of the order, the mode of the order,
status, shipping mode, total amount of the order, and the sales representative who helped place the
order. This may be the same individual as the account manager for a customer, it may be a different
individual, or, in the case of an order over the Internet, the sales representative is not recorded. In
addition to the order information, the company also tracks the number of items ordered, the unit
price, and the products ordered.
For each country in which it does business, the company records the country name, currency symbol,
currency name, and the region where the country resides geographically. This data is useful to
interact with customers living in different geographic regions around the world.
SYSTOOLS
SYSTOOLS
SYSTOOLS
SYSTOOLS
SYSTOOLS
SELECT COUNT(*) FROM customers;
COUNT(*)
----------
319
SYSTOOLS
----------
665
SYSTOOLS
SYSTOOLS
identification code, salary, and manager. Some employees earn a commission in addition to their
salary.
The company also tracks information about the jobs within the organization. Each job has an
identification code, job title, and a minimum and maximum salary range for the job. Some employees
have been with the company for a long time and have held different positions within the company.
When an employee switches jobs, the company records the start date and end date of the former job,
the job identification number, and the department.
The sample company is regionally diverse, so it tracks the locations of not only its warehouses but
also its departments. Each company employee is assigned to a department. Each department is
identified by a unique department number and a short name. Each department is associated with one
location. Each location has a full address that includes the street address, postal code, city, state or
province, and country code.
For each location where it has facilities, the company records the country name, currency symbol,
currency name, and the region where the country resides geographically.
SYSTOOLS
SYSTOOLS
SYSTOOLS
COUNT(*)
----------
107
SYSTOOLS
----------
25
SYSTOOLS
10
SYSTOOLS
SYSTOOLS
SYSTOOLS
Using SQL Developer
SYSTOOLS
Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Objectives
SYSTOOLS
After completing this appendix, you should be able to do the
following:
• List the key features of Oracle SQL Developer
• Install Oracle SQL Developer
• Identify menu items of Oracle SQL Developer
• Create a database connection
• Manage database objects
• Use SQL worksheet
• Save and run SQL scripts
SYSTOOLS
• Create and save reports
Objectives
In this appendix, you are introduced to the graphical tool called SQL Developer. You learn how to
use SQL Developer for your database development tasks. You learn how to use SQL worksheet to
execute SQL statements and SQL scripts.
SYSTOOLS
SYSTOOLS
• Oracle SQL Developer is a graphical tool that enhances
productivity and simplifies database development tasks.
• You can connect to any target Oracle database schema by
using standard Oracle database authentication.
SYSTOOLS
SQL Developer
SYSTOOLS
• Browsing and managing database objects
• Executing SQL statements and scripts
• Editing and debugging PL/SQL statements
• Creating reports
You can connect to any target Oracle database schema by using the standard Oracle database
authentication. When connected, you can perform operations on objects in the database.
Note: The SQL Developer 1.2 release is called the Migration release, because it tightly integrates
with Developer Migration Workbench that provides users with a single point to browse database
objects and data in third-party databases, and to migrate from these databases to Oracle. You can also
connect to schemas for selected third-party (non-Oracle) databases, such as MySQL, Microsoft SQL
Server, and Microsoft Access, and you can view metadata and data in these databases.
Additionally, SQL Developer 1.2 includes support for Oracle Application Express 3.0.1 (Oracle
APEX).
•
•
SYSTOOLS
Developed in Java
Supports Windows, Linux, and Mac OS X platforms
• Default connectivity by using the JDBC Thin driver
• Does not require an installer
– Unzip the downloaded SQL Developer kit and double-click
sqldeveloper.exe to start SQL Developer.
• Connects to any Oracle Database version 9.2.0.1 and later
• Freely downloadable from the following link:
– http://www.oracle.com/technology/software/products/sql/
SYSTOOLS
index.html
• Needs JDK 1.5 to be installed on your system. It can be
downloaded from the following link:
– http://java.sun.com/javase/downloads/index_jdk5.jsp
SYSTOOLS
Default connectivity to the database is through the Java Database Connectivity (JDBC) Thin driver,
and therefore, no Oracle Home is required. SQL Developer does not require an installer and you need
to simply unzip the downloaded file. With SQL Developer, users can connect to Oracle Databases
9.2.0.1 and later, and all Oracle database editions, including Express Edition.
SQL Developer can be downloaded with the following packaging options:
• Oracle SQL Developer for Windows (option to download with or without Java Development Kit
[JDK] 1.5)
• Oracle SQL Developer for Multiple Platforms (JDK 1.5 should already be installed.)
• Oracle SQL Developer for Mac OS X platforms (JDK 1.5 should already be installed.)
• Oracle SQL Developer Red Hat Package Manager (RPM) for Linux (JDK 1.5 should already be
installed.)
SYSTOOLS
Download the Oracle SQL Developer kit and unzip into any
directory on your machine.
SYSTOOLS
C-5 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
2. Download the SQL Developer kit from
http://www.oracle.com/technology/software/products/sql/index.html.
3. Unzip the downloaded SQL Developer kit into the folder that was created in step 1.
To start SQL Developer, go to <local drive>:\SQL Developer, and double-click
sqldeveloper.exe.
SYSTOOLS
You must define a
connection to start
using SQL Developer
for running SQL queries
on a database schema.
SYSTOOLS
C-6 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SQL Developer uses the left side for navigation to find and select objects, and the right side to
display information about the selected objects. You can customize many aspects of the appearance
and behavior of SQL Developer by setting preferences.
The menus at the top contain standard entries, plus entries for features specific to SQL Developer:
• View: Contains options that affect what is displayed in the SQL Developer interface
• Navigate: Contains options for navigating to panes and for executing subprograms
• Run: Contains the Run File and the Execution Profile options that are relevant when a function
or procedure is selected
• Debug: Contains options that are relevant when a function or procedure is selected for
debugging
• Source: Contains options for use when editing functions and procedures
• Migration: Contains options related to migrating third-party databases to Oracle
• Tools: Invokes SQL Developer tools, such as SQL*Plus, Preferences, and SQL worksheet
Note: You need to define at least one connection to be able to connect to a database schema and
issue SQL queries or run procedures or functions.
Oracle Database 11g: Advanced PL/SQL C - 6
Creating a Database Connection
SYSTOOLS
• You must have at least one database connection to use SQL
Developer.
• You can create and test connections:
– For multiple databases
– For multiple schemas
• SQL Developer automatically imports connections defined in
the tnsnames.ora file on your system.
• You can export connections to an XML file.
• Each additional database connection that is created is listed
SYSTOOLS
in the Connections navigator hierarchy.
SYSTOOLS
By default, the tnsnames.ora file is located in the $ORACLE_HOME/network/admin
directory. But, it can also be in the directory specified by the TNS_ADMIN environment variable or
registry value. When you start SQL Developer and display the Database Connections dialog box,
SQL Developer automatically imports any connections defined in the tnsnames.ora file on your
system.
Note: On Windows systems, if the tnsnames.ora file exists but its connections are not being
used by SQL Developer, define TNS_ADMIN as a system environment variable.
You can export connections to an XML file so that you can reuse it later.
You can create additional connections as different users to the same database or to connect to the
different databases.
SYSTOOLS 1
SYSTOOLS
C-8 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
3. From the Role drop-down list, select either default or SYSDBA. (Choose SYSDBA for the sys
user or any user with DBA privileges.)
4. Select the connection type:
- Basic: In this type, enter host name and SID for the database that you want to connect to.
Port is already set to 1521. Or, you can also choose to enter the Service name directly if you
are using a remote database connection.
- TNS: You can select any one of the database aliases imported from the tnsnames.ora file.
- Advanced: You can define a custom JDBC URL to connect to the database.
5. Click Test to make sure that the connection was set correctly.
6. Click Connect.
If you select the Save Password check box, the password is saved to an XML file. So, after you
close the SQL Developer connection and open it again, you are not prompted for the password.
SYSTOOLS
and so on.
Note: From the same New/Select Database Connection window, you can define connections to non-
Oracle data sources by using the Access, MySQL, and SQL Server tabs. However, these connections
are read-only connections that enable you to browse objects and data in that data source.
SYSTOOLS
SYSTOOLS
SYSTOOLS
Use the Connections navigator to:
• Browse through many objects in a database schema
• Review the definitions of objects at a glance
SYSTOOLS
C - 10 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
display information about the selected objects. You can customize many aspects of the appearance of
SQL Developer by setting preferences.
You can see the definition of the objects broken into tabs of information that is pulled from the data
dictionary. For example, if you select a table in the navigator, the details about columns, constraints,
grants, statistics, triggers, and so on are displayed on an easy-to-read tabbed page.
If you want to see the definition of the EMPLOYEES table as shown in the slide, perform the
following steps:
1. Expand the Connections node in the Connections navigator.
2. Expand Tables.
3. Click EMPLOYEES. By default, the Columns tab is selected. It shows the column description of
the table. On the Data tab, you can view the table data and also enter new rows, update data, and
commit these changes to the database.
SYSTOOLS
• SQL Developer supports the creation of any schema object
by:
– Executing a SQL statement in SQL worksheet
– Using the context menu
• Edit the objects by using an edit dialog or one of the many
context-sensitive menus.
• View the DDL for adjustments, such as creating a new object
or editing an existing schema object.
SYSTOOLS
C - 11 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
those adjustments is available for review. An Export DDL option is available if you want to create
the full DDL for one or more objects in the schema.
The slide shows how to create a table by using the context menu. To open a dialog box for creating a
new table, right-click Tables and select New Table. The dialog boxes for creating and editing
database objects have multiple tabs, each reflecting a logical grouping of properties for that type of
object.
SYSTOOLS
SYSTOOLS
C - 12 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
The example in the slide shows how to create the DEPENDENTS table by selecting the Advanced
check box.
To create a table, perform the following steps:
1. In the Connections navigator, right-click Tables.
2. Select New Table.
3. In the Create Table dialog box, select Advanced.
4. Specify column information.
5. Click OK.
Although it is not required, you should also specify a primary key by using the Primary Key tab in
the dialog box. Sometimes, you may want to edit the table that you created. To edit a table, right-
click the table in the Connections navigator and select Edit.
SYSTOOLS
• Use the SQL worksheet to enter and execute SQL, PL/SQL,
and SQL*Plus statements.
• Specify actions that can be processed by the database
connection associated with the worksheet.
Enter SQL
statements.
SYSTOOLS
SQL worksheet before being passed to the database.
The SQL worksheet currently supports a number of SQL*Plus commands. Commands not supported
by the SQL worksheet are ignored and are not sent to the Oracle database. Through the SQL
worksheet, you can execute SQL statements and some of the SQL*Plus commands.
You can display a SQL worksheet by using any of the following options:
• Select Tools > SQL Worksheet.
• Click the Open SQL Worksheet icon.
SYSTOOLS
1 2 4 6 8 9
5 7
3
SYSTOOLS
C - 14 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Alternatively, you can press F9. The output is generally shown in a formatted manner on the
Results tabbed page.
2. Run Script: Executes all statements in the Enter SQL Statement box by using the Script
Runner. The output is generally shown in the conventional script format on the Scripts tab page.
3. Commit: Writes changes to the database, and ends the transaction.
4. Rollback: Discards changes to the database, without writing them to the database, and ends the
transaction.
5. Cancel: Stops the execution of statements that are being executed.
SYSTOOLS
7. Execute Explain Plan: Generates the execution plan, which you can see by clicking the Explain
tab.
8. Autotrace: Displays trace-related information when you execute the SQL statement by clicking
the Autotrace icon. This information can help you identify SQL statements that will benefit from
tuning.
9. Clear: Erases the statements in the Enter SQL Statement box. Alternatively, press Ctrl + D to
erase the statements.
SYSTOOLS
SYSTOOLS
SYSTOOLS
Use the Enter SQL Statement box to enter single or multiple
SQL statements.
F9 F5
F5
F9
SYSTOOLS
C - 16 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Alternatively, you can press the F9 key.
To execute multiple SQL statements and see the results, click the Run Script icon. Alternatively,
you can press the F5 key.
The example in the slide shows the difference in output for the same query when the F9 key or
Execute Statement is used versus the output when F5 or Run Script is used.
SYSTOOLS
Before
formatting
SYSTOOLS
After
formatting
SYSTOOLS
statement is not properly indented. After formatting, the SQL code is formatted with the keywords
capitalized and the statement properly indented.
SYSTOOLS 1
2
3
SYSTOOLS
C - 18 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
2. In the Save dialog box, enter the file name. Make sure that the extension is .sql or the File
type is selected as SQL Script (*.sql). Click Save. Note: For this course, you need to save your
SQL scripts in the D:\labs\sql1\labs folder.
3. The SQL worksheet is renamed as the file name that you saved the script as. Make sure that you
do not enter any other SQL statements in the same worksheet. To continue with other SQL
queries, open a new worksheet.
SYSTOOLS
1
SYSTOOLS 2
SYSTOOLS
saved the script file, select the file, and click Open.
3. The script file opens in a new worksheet. Now, you can run the script by either clicking the
Execute Statement icon or the Run Script icon. Again, make sure that you do not enter any other
SQL statements in the same worksheet. To continue with other SQL queries, open a new
worksheet.
SYSTOOLS
Snippets are code fragments that may be just syntax or
examples.
When you place your cursor here,
it shows the Snippets window.
From the drop-down list, you can
select the functions category.
SYSTOOLS
C - 20 Copyright © 2008, Oracle. All rights reserved.
Using Snippets
You may want to use certain code fragments when you are using the SQL worksheet, or creating or
editing a PL/SQL function or procedure. SQL Developer has a feature called Snippets. Snippets are
code fragments, such as SQL functions, Optimizer hints, and miscellaneous PL/SQL programming
techniques. You can drag snippets to the Editor window.
SYSTOOLS
To display Snippets, select View > Snippets.
The Snippets window appears on the right side. You can use the drop-down list to select a group. A
Snippets button is placed in the right window margin, so that you can display the Snippets window if
it becomes hidden.
SYSTOOLS
Inserting a
snippet
Editing the
snippet
SYSTOOLS
C - 21 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
The example in the slide shows that CONCAT(char1, char2) is dragged from the Character
Functions group in the Snippets window. Then, the CONCAT function syntax is edited and the rest of
the statement is added such as in the following:
SELECT CONCAT(first_name, last_name)
FROM employees;
SYSTOOLS
• You can invoke the SQL*Plus command-line interface from
SQL Developer.
• Close all SQL worksheets to enable the SQL*Plus menu
option.
Provide the
SYSTOOLS
location of the
sqlplus.exe
file only the
first time you
invoke
SQL*Plus.
Using SQL*Plus
The SQL worksheet supports most of the SQL*Plus statements. SQL*Plus statements must be
interpreted by the SQL worksheet before being passed to the database; any SQL*Plus statements that
are not supported by the SQL worksheet are ignored and not passed to the database. To display the
SQL*Plus command window, from the Tools menu, select SQL*Plus. To use this feature, the system
SYSTOOLS
on which you are using SQL Developer must have an Oracle home directory or folder, with a
SQL*Plus executable under that location. If the location of the SQL*Plus executable is not already
stored in your SQL Developer preferences, you are asked to specify its location.
For example, some of the SQL*Plus statements that are not supported by SQL worksheet are:
• append
• archive
• attribute
• break
For a complete list of the SQL*Plus statements that are either supported or not supported by SQL
worksheet, refer to the “SQL*Plus Statements Supported and Not Supported in SQL Worksheet”
topic in SQL Developer online Help.
SYSTOOLS
• Use SQL Developer to debug PL/SQL functions and
procedures.
• Use the Compile for Debug option to perform a PL/SQL
compilation so that the procedure can be debugged.
• Use the Debug menu options to set breakpoints and to
perform step into, step
over tasks.
SYSTOOLS
C - 23 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
• Step Over bypasses the next method and goes to the next statement after the method.
• Step Into goes to the first statement in the next method.
• Step Out leaves the current method and goes to the next statement.
• Step to End of Method goes to the last statement of the current method.
• Pause halts execution but does not exit, thus allowing you to resume execution.
• Terminate halts and exits the execution. You cannot resume execution from this point; instead,
to start running or debugging from the beginning of the function or procedure, click the Run or
Debug icon on the Source tab toolbar.
• Garbage Collection removes invalid objects from the cache in favor of more frequently
accessed and more valid objects.
SYSTOOLS
SQL Developer provides a number of predefined reports about
the database and its objects.
SYSTOOLS
C - 24 Copyright © 2008, Oracle. All rights reserved.
Database Reporting
SQL Developer provides many reports about the database and its objects. These reports can be
grouped into the following categories:
• About Your Database reports
• Database Administration reports
SYSTOOLS
• Table reports
• PL/SQL reports
• Security reports
• XML reports
• Jobs reports
• Streams reports
• All Objects reports
• Data Dictionary reports
• User-Defined reports
To display reports, click the Reports tab on the left side of the window. Individual reports are
displayed in tabbed panes on the right side of the window; and for each report, you can select (using
a drop-down list) the database connection for which to display the report. For reports about objects,
the objects shown are only those visible to the database user associated with the selected database
connection, and the rows are usually ordered by Owner. You can also create your own user-defined
reports.
SYSTOOLS
Create and save user-defined reports for repeated use.
SYSTOOLS
information for the report, and click Apply.
In the example in the slide, the report name is specified as emp_sal. An optional description
indicates that the report contains details of employees with salary >= 10000. The complete
SQL statement for retrieving the information to be displayed in the user-defined report is specified in
the SQL box. You can also include an optional tool tip to be displayed when the cursor hovers over
the report name in the Reports navigator display.
You can organize user-defined reports in folders, and you can create a hierarchy of folders and
subfolders. To create a folder for user-defined reports, right-click the User Defined Reports node or
any folder name under that node and select Add Folder. Information about user-defined reports,
including any folders for these reports, is stored in a file named UserReports.xml under the
directory for user-specific information.
SYSTOOLS Shortcuts to
frequently used tools
1
SYSTOOLS
Links to popular
search engines and
discussion forums
SYSTOOLS
frequently. To do so, perform the following:
1. From the Tools menu, select External Tools.
2. In the External Tools dialog box, select New to add new tools. Select Delete to remove any tool
from the list.
SYSTOOLS
• Customize the SQL Developer interface and environment.
• From the Tools menu, select Preferences.
SYSTOOLS
C - 27 Copyright © 2008, Oracle. All rights reserved.
Setting Preferences
You can customize many aspects of the SQL Developer interface and environment by modifying the
SQL Developer preferences according to your preferences and needs. To modify the SQL Developer
preferences, select Tools, and then Preferences.
The preferences are grouped in the following categories:
SYSTOOLS
• Environment
• Accelerators (Keyboard shortcuts)
• Code Editors
• Database
• Debugger
• Documentation
• Extensions
• File Types
• Migration
• PL/SQL Compilers
• PL/SQL Debugger, and so on
SYSTOOLS
In this appendix, you should have learned how to use SQL
Developer to do the following:
• Browse, create, and edit database objects
• Execute SQL statements and scripts in SQL worksheet
• Create and save custom reports
SYSTOOLS
C - 28 Copyright © 2008, Oracle. All rights reserved.
Summary
SQL Developer is a free graphical tool to simplify the database development tasks. Using SQL
Developer, you can browse, create, and edit database objects. You can use SQL worksheet to run
SQL statements and scripts. SQL Developer enables you to create and save your own special set of
reports for repeated use.
SYSTOOLS
SYSTOOLS
Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Objectives
SYSTOOLS
After completing this appendix, you should be able to do the
following:
• Log in to SQL*Plus
• Edit SQL commands
• Format output using SQL*Plus commands
• Interact with script files
SYSTOOLS
D-2 Copyright © 2008, Oracle. All rights reserved.
Objectives
You might want to create SELECT statements that can be used again and again. This appendix also
covers the use of SQL*Plus commands to execute SQL statements. You learn how to format output
using SQL*Plus commands, edit SQL commands, and save scripts in SQL*Plus.
SYSTOOLS
Query results
Buffer
SYSTOOLS SQL
scripts
SYSTOOLS
execution. It contains its own command language.
Features of SQL
• Can be used by a range of users, including those with little or no programming experience
• Is a nonprocedural language
• Reduces the amount of time required for creating and maintaining systems
• Is an English-like language
Features of SQL*Plus
• Accepts ad hoc entry of statements
• Accepts SQL input from files
• Provides a line editor for modifying SQL statements
• Controls environmental settings
• Formats query results into basic reports
• Accesses local and remote databases
SYSTOOLS
SQL*Plus Commands
SQL SQL*Plus
• A language • An environment
• ANSI-standard • Oracle-proprietary
• Keywords cannot be • Keywords can be
abbreviated abbreviated
• Statements manipulate • Commands do not allow
data and table manipulation of values in
definitions in the the database
database
SYSTOOLS
SQL
statements
SQL
buffer
SQL*Plus
commands
SQL*Plus
buffer
SQL SQL*Plus
Is a language for communicating with the Recognizes SQL statements and sends them
SYSTOOLS
Oracle server to access data to the server
Is based on American National Standards Is the Oracle-proprietary interface for
Institute (ANSI)–standard SQL executing SQL statements
Manipulates data and table definitions in the Does not allow manipulation of values in the
database database
Is entered into the SQL buffer on one or Is entered one line at a time, not stored in the
more lines SQL buffer
Does not have a continuation character Uses a dash (–) as a continuation character if
the command is longer than one line
Cannot be abbreviated Can be abbreviated
Uses a termination character to execute Does not require termination characters;
commands immediately executes commands immediately
Uses functions to perform some formatting Uses commands to format data
•
•
SYSTOOLS
Log in to SQL*Plus.
Describe the table structure.
• Edit your SQL statement.
• Save SQL statements to files and append SQL statements
to files.
• Execute saved files.
• Load commands from file to buffer to edit.
SYSTOOLS
D-5 Copyright © 2008, Oracle. All rights reserved.
SQL*Plus: Overview
SQL*Plus is an environment in which you can perform the following:
• Execute SQL statements to retrieve, modify, add, and remove data from the database.
• Format, perform calculations on, store, and print query results in the form of reports.
• Create script files to store SQL statements for repeated use in the future.
SYSTOOLS
SQL*Plus commands can be divided into the following main categories:
Category Purpose
Environment Affect the general behavior of SQL statements for the session
Format Format query results
File manipulation Save, load, and run script files
Entry Send SQL statements from the SQL buffer to the Oracle server
Edit Modify SQL statements in the buffer
Interaction Create and pass variables to SQL statements, print variable values, and
print messages to the screen
Miscellaneous Connect to the database, manipulate the SQL*Plus environment, and
display column definitions
SYSTOOLS
1
SYSTOOLS
D-6 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
2. Enter the username, password, and database name.
To log in from a command-line environment:
1. Log in to your machine.
2. Enter the sqlplus command shown in the slide.
In the syntax:
username Your database username
password Your database password (Your password is visible if you enter it here.)
@database The database connect string
Note: To ensure the integrity of your password, do not enter it at the operating system prompt.
Instead, enter only your username. Enter your password at the password prompt.
SYSTOOLS
SYSTOOLS
D-7 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Screen Text.
SYSTOOLS
Use the SQL*Plus DESCRIBE command to display the structure
of a table:
DESC[RIBE] tablename
SYSTOOLS
D-8 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
tablename Is the name of any existing table, view, or synonym that is accessible to
the user
To describe the JOB_GRADES table, use this command:
SQL> DESCRIBE job_grades
Name Null? Type
---------------------------------- -------- -----------
GRADE_LEVEL VARCHAR2(3)
LOWEST_SAL NUMBER
HIGHEST_SAL NUMBER
SYSTOOLS
DESCRIBE departments
SYSTOOLS
D-9 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Type: Displays the data type for a column
The following table describes the data types:
•
•
SYSTOOLS
A[PPEND] text
C[HANGE] / old / new
• C[HANGE] / text /
• CL[EAR] BUFF[ER]
• DEL
• DEL n
• DEL m n
SYSTOOLS
D - 10 Copyright © 2008, Oracle. All rights reserved.
CL[EAR] BUFF[ER]
DEL
SYSTOOLS
C[HANGE] / text / Deletes text from the current line
Deletes all lines from the SQL buffer
Deletes current line
DEL n Deletes line n
DEL m n Deletes lines m to n
Guidelines
• If you press Enter before completing a command, SQL*Plus prompts you with a line number.
• You terminate the SQL buffer by either entering one of the terminator characters (semicolon or
slash) or by pressing Enter twice. The SQL prompt then appears.
•
•
SYSTOOLS
I[NPUT]
I[NPUT] text
• L[IST]
• L[IST] n
• L[IST] m n
• R[UN]
• n
• n text
• 0 text
SYSTOOLS
D - 11 Copyright © 2008, Oracle. All rights reserved.
Command Description
I[NPUT] Inserts an indefinite number of lines
I[NPUT] text Inserts a line consisting of text
L[IST] Lists all lines in the SQL buffer
SYSTOOLS
L[IST] n Lists one line (specified by n)
L[IST] m n Lists a range of lines (m to n)
R[UN] Displays and runs the current SQL statement in the buffer
n Specifies the line to make the current line
n text Replaces line n with text
0 text Inserts a line before line 1
Note: You can enter only one SQL*Plus command for each SQL prompt. SQL*Plus commands are
not stored in the buffer. To continue a SQL*Plus command on the next line, end the first line with a
hyphen (-).
LIST SYSTOOLS
1 SELECT last_name
2* FROM employees
1
1* SELECT last_name
A , job_id
1* SELECT last_name, job_id
LIST
SYSTOOLS
1 SELECT last_name, job_id
2* FROM employees
SYSTOOLS
• Use the A[PPEND] command to add text to the current line. The newly edited line is displayed.
Verify the new contents of the buffer by using the LIST command.
Note: Many SQL*Plus commands, including LIST and APPEND, can be abbreviated to just their
first letters. LIST can be abbreviated to L; APPEND can be abbreviated to A.
LIST
SYSTOOLS
1* SELECT * from employees
c/employees/departments
1* SELECT * from departments
LIST
SYSTOOLS
1* SELECT * from departments
SYSTOOLS
• Use the L[IST] command to verify the new contents of the buffer.
•
•
SYSTOOLS
SAVE filename
GET filename
• START filename
• @ filename
• EDIT filename
• SPOOL filename
• EXIT
SYSTOOLS
D - 14 Copyright © 2008, Oracle. All rights reserved.
Command Description
SYSTOOLS
SAV[E] filename [.ext] Saves the current contents of the SQL buffer to a file. Use
[REP[LACE]APP[END]] APPEND to add to an existing file; use REPLACE to
overwrite an existing file. The default extension is .sql.
GET filename [.ext] Writes the contents of a previously saved file to the SQL
buffer. The default extension for the file name is .sql.
STA[RT] filename [.ext] Runs a previously saved command file.
@ filename Runs a previously saved command file (same as START).
ED[IT] Invokes the editor and saves the buffer contents to a file
named afiedt.buf.
ED[IT] [filename[.ext]] Invokes the editor to edit the contents of a saved file.
SPO[OL] [filename[.ext]| Stores query results in a file. OFF closes the spool file. OUT
OFF|OUT] closes the spool file and sends the file results to the printer.
EXIT Quits SQL*Plus.
LIST SYSTOOLS
1 SELECT last_name, manager_id, department_id
2* FROM employees
SAVE my_query
Created file my_query
START my_query
SYSTOOLS
King 90
Kochhar 100 90
...
107 rows selected.
SYSTOOLS
Use the START command to run a script in SQL*Plus.
SYSTOOLS
EDIT my_query
SYSTOOLS
D - 16 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
Oracle Database 10g
• Changes to the SET SERVEROUT[PUT] command
• White space support in file and path names in Windows
• Three new predefined SQL*Plus variables
• The new RECYCLEBIN clause of the SHOW command
• The new APPEND, CREATE, and REPLACE extensions to the
SPOOL command
• New error messages for the COPY command
• Change in the DESCRIBE command behavior
• New PAGESIZE default
•
• SYSTOOLS
New SQLPLUS program compatibility option
Execution statistics information in the AUTOTRACE command
report
SYSTOOLS
SYSTOOLS
• Use the SET SERVEROUT[PUT] command to control whether to
display the output of stored procedures or PL/SQL blocks in
SQL*Plus.
• The DBMS_OUTPUT line length limit is increased from 255 bytes to
32,767 bytes.
• The default size is now unlimited.
• Resources are not preallocated when SERVEROUTPUT is set.
• Because there is no performance penalty, use UNLIMITED unless
you want to conserve physical memory.
SYSTOOLS
SET SERVEROUT[PUT] {ON | OFF} [SIZE {n | UNL[IMITED]}]
[FOR[MAT] {WRA[PPED] | WOR[D_WRAPPED] | TRU[NCATED]}]
SYSTOOLS
data passed to DBMS_OUTPUT.
SQL*Plus does not display DBMS_OUTPUT data unless you first issue the SQL*Plus command SET
SERVEROUTPUT ON as follows:
SET SERVEROUTPUT ON
Note
• SIZE sets the number of bytes of the output that can be buffered within the Oracle Database
server. The default is UNLIMITED. n cannot be less than 2,000 or greater than 1,000,000.
• For additional information about SERVEROUTPUT, see the Oracle Database PL/SQL User’s
Guide and Reference 11g Release 1 (11.1).
SYSTOOLS
and Path Names in Windows
• In Windows, white space can be included in file names and
paths.
• Examples of where white space can be used:
– START, @, @@, RUN, SPOOL, SAVE, and EDIT commands
• To reference files or paths containing spaces, enclose the
name or path in double quotation marks.
Examples
SYSTOOLS
START "Monthly Report.sql"
SYSTOOLS
SYSTOOLS
Variable Name
_CONNECT_IDENTIFIER
Contains
Connection identifier used to make the connection,
where available
SYSTOOLS
_SQLPLUS_RELEASE Full release number of the installed SQL*Plus
component
SYSTOOLS
substitution variables, or in your SQL*Plus command-line prompt.
You can use the DEFINE command to view the definitions of these eight predefined variables in the
same way as you view the other DEFINE definitions. You can also use the DEFINE command to
redefine their values, or you can use the UNDEFINE command to remove their definitions and make
them unavailable.
Note: For additional information about the SQL*Plus predefined variables, see the SQL*Plus User’s
Guide and Reference Release 11.1.
SYSTOOLS
SQL*Plus Variables: Examples
-- Change the SQL*Plus prompt to display the connection
-- identifier
SYSTOOLS
-- View the user name connected to the current
-- connection.
SYSTOOLS
DEFINE _USER = "HR" (CHAR)
DEFINE _PRIVILEGE = "" (CHAR)
DEFINE _SQLPLUS_RELEASE = "1002000100" (CHAR)
DEFINE _EDITOR = "Notepad" (CHAR)
DEFINE _O_VERSION = "Oracle Database 10g Enterprise Edition
Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options" (CHAR)
DEFINE _O_RELEASE = "1002000100" (CHAR)
You can use UNDEFINE to remove a substitution variable definition and make it unavailable.
SYSTOOLS
RECYCLEBIN Clause
SHOW RECYC[LEBIN] [original_name]
SELECT * FROM USER_RECYCLEBIN
desc user_recyclebin;
Name Null? Type
--------------- -------- ------------
OBJECT_NAME NOT NULL VARCHAR2(30)
ORIGINAL_NAME VARCHAR2(32)
OPERATION VARCHAR2(9)
TYPE VARCHAR2(25)
TS_NAME VARCHAR2(30)
CREATETIME VARCHAR2(19)
DROPTIME VARCHAR2(19)
DROPSCN NUMBER
PARTITION_NAME VARCHAR2(32)
SYSTOOLS
CAN_UNDROP VARCHAR2(3)
CAN_PURGE VARCHAR2(3)
RELATED NOT NULL NUMBER
BASE_OBJECT NOT NULL NUMBER
PURGE_OBJECT NOT NULL NUMBER
SPACE NUMBER
SYSTOOLS
SELECT * FROM USER_RECYCLEBIN
SYSTOOLS
RECYCLEBIN Clause: Example
SHOW recyclebin
SYSTOOLS
D - 23 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
SPO[OL] [file_name[.ext] [CRE[ATE] | REP[LACE] |
APP[END]] | OFF | OUT]
Option Description
APP[END] Adds the contents of the buffer to the end of the file
SYSTOOLS
you specify
SYSTOOLS
use SET TERMOUT OFF. SET TERMOUT OFF does not affect the output from commands that run
interactively.
You must use quotation marks around file names containing white spaces. To create a valid HTML
file using the SPOOL APPEND commands, you must use PROMPT or a similar command to create
the HTML page header and footer. The SPOOL APPEND command does not parse HTML tags. Set
SQLPLUSCOMPAT[IBILITY] to 9.2 or earlier to disable the CREATE, APPEND, and SAVE
parameters.
SYSTOOLS
-- Record the output in the new file DIARY using the
-- default file extension.
SYSTOOLS
SPOOL DIARY REPLACE
SPOOL OUT
SYSTOOLS
SYSTOOLS
CPY-0002 Illegal or missing APPEND, CREATE, INSERT, or
REPLACE option
SYSTOOLS
CPY-0006 Select list has more columns than destination
Table
SYSTOOLS
CPY-0004 Source and destination table and column names don't match: On an APPEND
operation or an INSERT (when the table exists), at least one column name in the destination table
does not match the corresponding column name in the optional column name list or in the SELECT
command. To correct this, respecify the COPY command, making sure that the column names and
their respective order in the destination table match the column names and column order in the
optional column list or in the SELECT command.
CPY-0005 Source and destination column attributes don't match: On an APPEND operation or
an INSERT (when the table exists), at least one column in the destination table does not have the
same data type as the corresponding column in the SELECT command. To correct this, respecify the
COPY command, making sure that the data types for the items being selected agree with the
destination. Use TO_DATE, TO_CHAR, and TO_NUMBER to make conversions.
SYSTOOLS
number of columns in the destination table. To correct this, respecify the COPY command, making
sure that the number of columns being selected agrees with the number in the destination table.
CPY-0007 Select list has fewer columns than destination table: On an APPEND operation or
INSERT (when the table exists), the number of columns in the SELECT command is less than the
number of columns in the destination table. To correct this, respecify the COPY command, making
sure that the number of columns being selected agrees with the number in the destination table.
CPY-0008 More column list names than columns in the destination table: On an APPEND
operation or an INSERT (when the table exists), the number of columns in the column name list is
greater than the number of columns in the destination table. To correct this, respecify the COPY
command, making sure that the number of columns in the column list agrees with the number in the
destination table.
CPY-0009 Fewer column list names than columns in the destination table: On an APPEND
operation or an INSERT (when the table exists), the number of columns in the column name list is
less than the number of columns in the destination table. To correct this, respecify the COPY
SYSTOOLS
command, making sure that the number of columns in the column list agrees with the number in the
destination table.
CPY-0012 Datatype cannot be copied: An attempt was made to copy a data type that is not
supported in the COPY command. Data types supported by the COPY command are CHAR, DATE,
LONG, NUMBER, and VARCHAR2. To correct this, respecify the COPY command, making sure that
the unsupported data type column is removed.
SYSTOOLS
SYSTOOLS
CPY-0008 More column list names than columns in the
destination table
SYSTOOLS
D - 28 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• Prior to Oracle Database 10g, using DESCRIBE on an
invalidated object failed with the error:
— ORA-24372: invalid object for describe
• The DESCRIBE command continued to fail even if the object
had since been validated.
• Starting with Oracle Database 10g, the DESCRIBE command
now automatically validates the object and continues if the
validation is successful.
SYSTOOLS
D - 29 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• It sets the number of rows on each page of the output in
SQL*Plus.
• The default PAGESIZE has changed from 24 to 14.
• You can set PAGESIZE to zero to suppress all headings,
page breaks, titles, the initial blank line, and other formatting
information.
SYSTOOLS
D - 30 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
the Compatibility Option
Sets the value of the SQLPLUSCOMPATIBILITY system
variable to the SQL*Plus release specified by x.y[.z]
SYSTOOLS
SQLPLUS -C 10.2.0
SYSTOOLS
the default compatibility is 10.2.
• You can use the SQLPLUS -C[OMPATIBILITY] {x.y[.z]} command argument at
startup to set the compatibility mode of that session.
• You can use the SET SQLPLUSCOMPATIBILITY {x.y[.z]} command during a session
to set the SQL*Plus behavior you want for that session.
Note: For a list showing the release of SQL*Plus that introduced the behavior change, see
the “SQL*Plus Compatibility Matrix” topic in SQL*Plus User’s Guide and Reference
Release 11.1.
SYSTOOLS
• It displays a report after the successful execution of SQL
DML statements, such as SELECT, INSERT, UPDATE or
DELETE.
• The report can now include execution statistics and the
query execution path.
SYSTOOLS
SET AUTOTRACE ON
-- The AUTOTRACE report includes both the optimizer
-- execution path and the SQL statement execution
-- statistics.
SYSTOOLS
connecting to Oracle Database 10g (Release 10.1) or later. When you connect to an earlier database,
the older form of AUTOTRACE reporting is used.
The DBMS_XPLAN package provides an easy way to display the output of the EXPLAIN PLAN
command in several, predefined formats.
Notes
• For additional information about the package and subprograms, see the Oracle Database
PL/SQL Packages and Types Reference 10g Release 2 (10.2) guide or the subsequent versions of
this guide.
• For additional information about EXPLAIN PLAN, see Oracle Database SQL Reference 10g
Release 2 (10.2) or the subsequent versions of this reference.
• For additional information about Execution Plans and the statistics, see Oracle Database
Performance Tuning Guide 10g Release 2 (10.2) or the subsequent versions of this guide.
SYSTOOLS
DBMS_XPLAN.DISPLAY Package Function
SYSTOOLS
SET LINESIZE 130
SET PAGESIZE 0
SELECT * FROM table(DBMS_XPLAN.DISPLAY);
SYSTOOLS
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 57 | 6 (34)| 00:00:01 |
|* 1 | HASH JOIN | | 1 | 57 | 6 (34)| 00:00:01 |
|* 2 | TABLE ACCESS FULL| EMP | 1 | 37 | 3 (34)| 00:00:01 |
| 3 | TABLE ACCESS FULL| DEPT | 4 | 80 | 3 (34)| 00:00:01 |
---------------------------------------------------------------------------
15 rows selected.
SYSTOOLS
In this appendix, you should have learned how to use SQL*Plus
as an environment to perform the following:
• Execute SQL statements
• Edit SQL statements
• Format output
• Interact with script files
SYSTOOLS
D - 34 Copyright © 2008, Oracle. All rights reserved.
Summary
SQL*Plus is an execution environment that you can use to send SQL commands to the database
server and to edit and save SQL commands. You can execute commands from the SQL prompt or
from a script file.
SYSTOOLS
SYSTOOLS
Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
Objectives
SYSTOOLS
After completing this appendix, you should be able to do the
following:
• Log in to JDeveloper
• Create, compile, and run program units
• Debug PL/SQL programs
• Examine and modify variables
SYSTOOLS
E-2 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
SYSTOOLS
E-3 Copyright © 2008, Oracle. All rights reserved.
JDeveloper
Oracle JDeveloper 11g is an integrated development environment (IDE) for developing and
deploying Java applications and Web services. It supports every stage of the software development
life cycle (SDLC), from modeling through deploying. It has the features to use the latest industry
standards for Java, Extensible Markup Language (XML), and SQL while developing an application.
SYSTOOLS
Oracle JDeveloper 11g initiates a new approach to Java 2 Platform, Enterprise Edition (J2EE)
development with features that enable visual and declarative development. This innovative approach
makes J2EE development simple and efficient.
SYSTOOLS
SYSTOOLS
E-4 Copyright © 2008, Oracle. All rights reserved.
Connections Navigator
Using Oracle JDeveloper 11g, you can store the information necessary to connect to a database in an
object called “connection.” A connection is stored as part of the IDE settings, and can be exported
and imported for easy sharing among groups of users. A connection serves several purposes: from
browsing the database and building applications, all the way to deployment.
SYSTOOLS
SYSTOOLS
SYSTOOLS
E-5 Copyright © 2008, Oracle. All rights reserved.
Applications Navigator
The Applications navigator gives you a logical view of your application and the data it contains. The
Applications navigator provides an infrastructure that the different extensions can plug into and use
to organize their data and menus in a consistent, abstract manner. While the Applications navigator
can contain individual files (such as Java source files), it is designed to consolidate complex data.
SYSTOOLS
Complex data types such as entity objects, Unified Modeling Language (UML) diagrams, Enterprise
JavaBeans (EJB), or Web services appear in this navigator as single nodes. The raw files that make
up these abstract nodes appear in the Structure window.
SYSTOOLS
SYSTOOLS
E-6 Copyright © 2008, Oracle. All rights reserved.
Structure Window
The Structure window offers a structural view of the data in the document that is currently selected in
the active window of those windows that participate in providing structure: the navigators, the editors
and viewers, and the Property Inspector.
In the Structure window, you can view the document data in many ways. The structures available for
SYSTOOLS
display are based on the document type. For a Java file, you can view code structure, user interface
(UI) structure, or UI model data. For an XML file, you can view XML structure, design structure, or
UI model data.
The Structure window is dynamic, always tracking the current selection of the active window (unless
you freeze the window’s contents on a particular view), as is pertinent to the currently active editor.
When the current selection is a node in the navigator, the default editor is assumed. To change the
view of the structure for the current selection, click a different structure tab.
SYSTOOLS
SYSTOOLS
E-7 Copyright © 2008, Oracle. All rights reserved.
Editor Window
You can view all your project files in a single editor window, you can open multiple views of the
same file, or you can open multiple views of different files.
The tabs at the top of the editor window are the document tabs. Clicking a document tab gives that
file focus, bringing it to the foreground of the window in the current editor.
SYSTOOLS
The tabs at the bottom of the editor window for a given file are the editor tabs. Selecting an editor tab
opens the file in that editor.
SYSTOOLS
Before deploying the Java stored procedures, perform the
following steps:
SYSTOOLS
E-8 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
• loadjava loads the Java class containing the stored procedures to an Oracle database.
• publish generates the PL/SQL call–specific wrappers for the loaded public static methods.
Publishing enables the Java methods to be called as PL/SQL functions or procedures.
SYSTOOLS
SYSTOOLS
E-9 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
SYSTOOLS
E - 10 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
4. Right-click a folder corresponding to the object type (Procedures, Packages, and Functions).
5. Choose New PL/SQL object_type. The Create PL/SQL dialog box appears for the function,
package, or procedure.
6. Enter a valid name for the function, package, or procedure, and click OK.
A skeleton definition is created and opened in the Code Editor. You can then edit the subprogram to
suit your need.
SYSTOOLS
Compilation with errors
SYSTOOLS
Compilation without errors
Compiling
After editing the skeleton definition, you need to compile the program unit. Right-click the PL/SQL
object to be compiled in the Connections navigator, and select Compile. Alternatively, you can press
CTRL + SHIFT + F9 to compile.
SYSTOOLS
SYSTOOLS
SYSTOOLS
E - 12 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
SYSTOOLS
E - 13 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
• JDeveloper support two types of debugging:
– Local
– Remote
• You need the following privileges to perform PL/SQL
debugging:
– DEBUG ANY PROCEDURE
– DEBUG CONNECT SESSION
SYSTOOLS
E - 14 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
PL/SQL program that is compiled in the NATIVE mode. This mode is set in the database’s
init.ora file.
PL/SQL programs must be compiled with the DEBUG option enabled. This option can be enabled in
various ways. Using SQL*Plus, execute ALTER SESSION SET PLSQL_DEBUG = true to
enable the DEBUG option. Then you can create or recompile the PL/SQL program that you want to
debug. Another way of enabling the DEBUG option is by using the following command in SQL*Plus:
ALTER <procedure, function, package> <name> COMPILE DEBUG;
SYSTOOLS
SYSTOOLS
E - 15 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
test these objects in an automatic way. With Oracle JDeveloper 11g, you can run and debug PL/SQL
program units. For example, you can specify the parameters being passed or the values returned from
a function, thereby giving you more control over what is run and providing you output details about
what was tested.
Note: The procedures or functions in the Oracle database can be either stand-alone or within a
package.
SYSTOOLS
2. In the navigator, expand the Database node to display the specific database username and
schema name.
3. Expand the Schema node.
4. Expand the appropriate node depending on what you are debugging: Procedure, Function, or
Package body.
5. (Optional for debugging only) Select the function, procedure, or package that you want to debug
and double-click to open it in the Code Editor.
6. (Optional for debugging only) Set a breakpoint in your PL/SQL code by clicking to the left of
the margin.
Note: The breakpoint must be set on an executable line of code. If the debugger does not stop,
the breakpoint may have not been set on an executable line of code (ensure that the breakpoint is
verified). Also, verify that the debugging PL/SQL prerequisites are met. In particular, make sure
that the PL/SQL program is compiled in the INTERPRETED mode.
7. Make sure that either the Code Editor or the procedure in the navigator is currently selected.
8. Click the Debug button on the toolbar; or, if you want to run without debugging, click the Run
SYSTOOLS
button on the toolbar.
9. The Run PL/SQL dialog box appears.
- Select a target that is the name of the procedure or function that you want to debug. Note
that the content in the Parameters and PL/SQL Block boxes changes dynamically when the
target changes.
Note: You will have a choice of target only if you choose to run or debug a package that
contains multiple program units.
- The Parameters box lists the target’s arguments (if applicable).
- The PL/SQL Block box displays the code that was custom-generated by JDeveloper for the
selected target. Depending on what the function or procedure does, you may need to replace
the NULL values with reasonable values so that they are passed into the procedure,
function, or package. In some cases, you may need to write additional code to initialize the
values to be passed as arguments. In this case, you can edit the PL/SQL block text as
necessary.
SYSTOOLS
10. Click OK to execute or debug the target.
11. Analyze the output information that is displayed in the Log window.
In the case of functions, the return value is displayed. DBMS_OUTPUT messages are also displayed.
SYSTOOLS
SYSTOOLS
E - 17 Copyright © 2008, Oracle. All rights reserved.
Setting Breakpoints
You can use breakpoints to examine the values of the variables in your program. A breakpoint is a
trigger in a program that, when reached, pauses program execution thereby allowing you to examine
the values of some or all program variables. By setting breakpoints in potential problem areas of your
source code, you can run your program until its execution reaches a location you want to debug.
SYSTOOLS
When your program execution encounters a breakpoint, it pauses, and the debugger displays the line
containing the breakpoint in the Code Editor. You can then use the debugger to view the state of your
program. Breakpoints are flexible in that they can be set before you begin a program run or at any
time while you are debugging.
To set a breakpoint in the Code Editor, click the margin on the left, next to a line of executable code.
Breakpoints set on comment lines, blank lines, declaration, and any other nonexecutable lines of
code are not verified by the debugger and are treated as invalid.
SYSTOOLS
E - 18 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
the execution of the program and displays the results in the Debugging – Log area.
SYSTOOLS
Data window
SYSTOOLS
E - 19 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
the program to make the fix permanent.
You use the Data window to display information about the variables in your program. The Data
window displays the arguments, local variables, and static fields for the current context, which is
controlled by the selection in the Stack window. If you move to a new context, the Data window is
updated to show the data for the new context. If the current program was compiled without debug
information, you cannot see the local variables.
SYSTOOLS
SYSTOOLS
E - 20 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
Watches window
SYSTOOLS
E - 21 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
Stack window
SYSTOOLS
E - 22 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS
SYSTOOLS
SYSTOOLS
SYSTOOLS
In this appendix, you should have learned how to use
JDeveloper as an environment to do the following:
• Create, compile, and run program units
• Debug PL/SQL programs
• Examine and modify variables
SYSTOOLS
E - 24 Copyright © 2008, Oracle. All rights reserved.
SYSTOOLS