+ All Categories

9ib_SQL

Date post: 11-Apr-2015
Category:
Upload: api-3831209
View: 104 times
Download: 0 times
Share this document with a friend
177
SQL and PL/SQL Enhancements 1-1 ANSI/ISO SQL: 1999 Standard Support In Oracle9i
Transcript
Page 1: 9ib_SQL

SQL and PL/SQL Enhancements 1-1

ANSI/ISO SQL: 1999 Standard Support In Oracle9i

Page 2: 9ib_SQL

SQL and PL/SQL Enhancements 1-2

Objectives

After completing this lesson you should be able to describe:• SQL: 1999 compliant joins• CASE expressions• Scalar subqueries• Explicit DEFAULTS

Page 3: 9ib_SQL

SQL and PL/SQL Enhancements 1-3

Overview

Several new features have been included in Oracle9i so that Oracle will be in conformance with ANSI/ISO SQL: 1999. The most important ones are discussed in this lesson:– SQL: 1999 join compliance– Introduction of CASE expressions

– Introduction of scalar subqueries– Support for explicit DEFAULTS

Note: Through out this lesson the phrase "SQL: 1999" refers to the SQL 1999 notations of both ANSI and ISO standards

Page 4: 9ib_SQL

SQL and PL/SQL Enhancements 1-4

Applications for SQL: 1999 Features

• Allows Oracle SQL to support ANSI/ISO SQL: 1999 standards

• Easier migration of third party applications without modifying existing code

• Allows Oracle to provide ANSI/ISO standard functionality within the database

• Easier learning curve for customers moving from other database products

Page 5: 9ib_SQL

SQL and PL/SQL Enhancements 1-5

SQL: 1999 Joins

The SQL: 1999 join syntax used to differ from Oracle joins in the following ways– The join type is specified explicitly in the FROM clause in SQL: 1999 syntax

– The join condition is distinguished from the search condition in the WHERE clause and is specified in the ON clause

Page 6: 9ib_SQL

SQL and PL/SQL Enhancements 1-6

Types of SQL: 1999 Compliant Joins

• Cross joins• Natural joins• Using clause• Full or two sided outer joins• Arbitrary join conditions for joins

Note: The new SQL: 1999 compliant join syntax does not offer any performance benefits over the Oracle proprietary join syntax that existed is prior releases

Page 7: 9ib_SQL

SQL and PL/SQL Enhancements 1-7

Creating CROSS Joins

• The CROSS join produces the cross-product of

• two tables.

• This is the same as a Cartesian• product between the two tables. For example:

SELECT last_name, department_nameFROM employees

CROSS JOIN departments;

Creating CROSS JoinsThe above example gives the same results as :

SELECT last_name, department_name FROM employees, department;LAST_NAME DEPARTMENT_NAME------------------------- ------------------------------King AdministrationKochhar AdministrationDe Haan AdministrationHunold AdministrationErnst Administration…King MarketingKochhar MarketingDe Haan MarketingHunold MarketingErnst Marketing…

Page 8: 9ib_SQL

SQL and PL/SQL Enhancements 1-8

Creating NATURAL Joins

• The NATURAL join is based on all columns in the two tables that have the same name.

• It selects rows from the two tables that have equal values in all matched columns

• If the columns having the same names have different datatypes then an error is returned

• If the SELECT * syntax is used, then the common columns appear only once in the result set

• Qualifiers such as table names or aliases may not be used for those columns involved in the NATURAL join

Creating Natural JoinsIt was not possible to do a join without specifying the columns in the corresponding tables in prior releases of Oracle. In Oracle9i it is possible to let the join be automatically completed based on columns in the two tables which have matching datatypes and names using the keywords NATURAL JOIN.Note: the join can only happen on columns having the same names and compatible datatypes in both the tables. If the columns have the same name, but have incompatible datatypes then the NATURAL join syntax will cause errors.

Page 9: 9ib_SQL

SQL and PL/SQL Enhancements 1-9

Retrieving Records with Natural JoinsIn the above example the department table is joined to the location table by the location_id column which is the only column of the same name in both tables. If other common columns were present then the join would have used them all. This can also be written as

SELECT department_id, location_idFROM locations,department

WHERE departments.location_id = locations.location_id;

Retrieving Records with Natural Joins

DEPARTMENT_ID LOCATION_ID------------- -----------

20 180050 150050 150050 150050 1500

SELECT department_id, location_idFROM locations

NATURAL JOIN departments;

Page 10: 9ib_SQL

SQL and PL/SQL Enhancements 1-10

Creating Joins with the USING clause

• If several columns have the same names but all the datatypes do not match, then the NATURAL JOIN can be modified to contain the USING clause to specify those columns that should be used for an equi-join

• The columns referenced in the USING clause should not have a qualifier (table name or alias) anywhere in the SQL statement

• The key word NATURAL and the keyword USINGare mutually exclusive keywords

Creating Joins with the USING clauseNatural joins use all columns with matching names and datatypes to join the tables. The USING clause can be used to specify only those columns that should be used for an equi-join. The columns referenced in the USING clause should not have a qualifier( table name or alias) anywhere in the SQL statement . For example

SELECT l.city, d.department_nameFROM locations l JOIN departments d USING (location_id)

WHERE location_id = 1400 ;Is valid, but:

SELECT l.city, d.department_nameFROM locations l JOIN departments d USING (location_id)

WHERE d.location_id = 1400 ;is invalid because in the where clause we have qualified location_id with a table name.

The same restriction applies to NATURAL joins also. Therefore columns that have the same name in both tables have to be used without any qualifiers.In both NATURAL joins and Joins with the USING clause if the columns with the same name are collections or LOBS the join will not be allowed

Page 11: 9ib_SQL

SQL and PL/SQL Enhancements 1-11

Retrieving Records with the USING ClauseIn the above example we are able to join the employees table to the departments table based only on the common department_id column. In order for the USING clause to work the column names must be the same in both tables and must have compatible datatypes. Qualifiers such as aliases or table names may not be used

Retrieving Records with the USING Clause

EMPLOYEE_ID LAST_NAME LOCATION_ID----------- --------- -----------

200 Whalen 1700201 Hartstein 1800202 Goyal 1800124 Mourgos 1500141 Rajs 1500142 Davies 1500143 Matos 1500

...

SELECT e.employee_id, e.last_name, d.location_idFROM employees e JOIN departments d

USING (department_id);

Page 12: 9ib_SQL

SQL and PL/SQL Enhancements 1-12

Creating Joins With the ON clause

• The join condition for the natural join is basically an equi-join of all columns with the same name.

• To specify arbitrary conditions or specify columns to join, the ON clause is used .

• Separates the join condition from other "filter" conditions

• The ON clause makes code easy to understand

Creating Joins With the ON clauseThe ON clause is very similar to the WHERE clause used in earlier versions of the Oracle database. It allows the specification of additional predicates in addition to the JOIN itself. The keyword JOIN indicates the join conditions and Additional predicates can be specified using the AND, OR and NOT operators

Page 13: 9ib_SQL

SQL and PL/SQL Enhancements 1-13

Creating Joins With the ON ClauseThe ON clause can also be used to join columns which have different names as follows:SELECT e.last_name emp, m.last_name mgr

FROM employees e JOIN employees m ON ( e.manager_id =m.employee_id);

EMP MGR-------------------- -------------------------Kochhar KingDe Haan KingRaphaely King…Greenberg KochharWhalen Kochhar…Hunold De Haan …The above example is a self join of the employees table to itself based on the employee_id and manager columns.

Example of Retrieving Records with the ON Clause

EMPLOYEE_ID LAST_NAME DEPARTMENT_ID DEPARTMENT_ID LOCATION_ID----------- --------- ------------- ------------- -----------

200 Whalen 10 10 1700201 Hartstein 20 20 1800202 Goyal 20 20 1800124 Mourgos 50 50 1500141 Rajs 50 50 1500142 Davies 50 50 1500143 Matos 50 50 1500

...

SELECT e.employee_id, e.last_name, e.department_id, d.department_id,d.location_idFROM employees e JOIN departments d

ON (e.department_id = d.department_id);

Page 14: 9ib_SQL

SQL and PL/SQL Enhancements 1-14

Creating Complex Joins

ON clause allows the usage of– Subqueries– AND/OR operators– [NOT] EXISTS– [NOT] IN

Creating Complex JoinsSimilar to the WHERE clause, the ON clause also allows the usage of the logical operators as well as subqueries. The only difference between using a WHERE clause and the ON clause is the difference in syntax.

Page 15: 9ib_SQL

SQL and PL/SQL Enhancements 1-15

Join Predicates and the ON Clause

• You can separate join predicates from the other predicates by using the ON clause; this makes your code easier to understand.

• The ON clause allows any predicate, including the usage of subqueries and logical operators.

SELECT e.manager_id, e.last_name , d.department_id, d.location_id

FROM employees e JOIN departments d ON((e.department_id = d.department_id)

AND e.manager_id = 102 );

SELECT e.manager_id, e.last_name , d.department_id, d.location_id

FROM employees e JOIN departments d ON((e.department_id = d.department_id)

AND e.manager_id = 102 );

Join Predicates and the ON ClauseYou can use the ON clause for any join to separate the join predicates from the non-join predicates. In the above example we are trying to retrieve the names , department_names and locations of all employees working for manager 102. The above query can also be written as:

SELECT e.manager_id, e.last_name,d.department_id, d.location_id

FROM employees e JOINdepartments d ON

(e.department_id = d.department_id)WHERE e.manager_id = 102;

MANAGER_ID LAST_NAME DEPARTMENT_ID LOCATION_ID---------- ------------------------- ------------- -----------

102 Hunold 60 1400

Page 16: 9ib_SQL

SQL and PL/SQL Enhancements 1-16

Creating Multi-Table Joins With the ON clause

SELECT employee_id, city, department_name FROM locations l JOIN departments d

ON(l.location_id = d.location_id)JOIN employees e

ON(d.department_id = e.department_id);

EMPLOYEE_ID CITY DEPARTMENT_NAME----------- -------------- ----------------

100 Seattle Executive101 Seattle Executive102 Seattle Executive

…106 Southlake IT107 Southlake IT108 Seattle Finance109 Seattle Finance110 Seattle Finance

Multi table joinsA three way join is a join of three tables. In SQL:1999 compliant syntax, joins are performed from left to right so the first join to be performed is locations join departments. The first join condition can reference columns in locations and departments but cannot reference columns in employees. The second join condition can reference columns from all three tables.

Page 17: 9ib_SQL

SQL and PL/SQL Enhancements 1-17

INNER vs. OUTER Joins

• IN SQL: 1999 the join of two tables returning only matched rows is considered an INNER JOIN

• A join between two tables which returns the results of the INNER join as well as unmatched rows from the left (right) table is considered a LEFT(RIGHT)OUTER JOIN

• A join between two tables which returns the results of an INNER join as well as the results of both the LEFT and RIGHT outer joins in considered as a FULL OUTER JOIN

INNER vs. OUTER JoinsInner and outer joins were available in prior releases .The '(+)' symbol was used one of the tables to create outer joins.

Page 18: 9ib_SQL

SQL and PL/SQL Enhancements 1-18

Example of LEFT OUTER Joins

SELECT e.last_name , d.department_nameFROM employees e LEFT OUTER JOIN departments d

ON(e.department_id = d.department_id)

LAST_NAME DEPARTMENT_NAME------------------------- --------------------Faviet FinanceGreenberg FinanceGietz AccountingHiggens AccountingGrant…

Example of LEFT OUTER JoinsThis query retrieves all rows in the EMPLOYEES table which is the left table even if there is no match in DEPARTMENTSThis query was completed in earlier releases as follows:SELECT e.last_name , d.department_nameFROM employees e, departments d

WHERE e.department_id = d.department_id(+)

Page 19: 9ib_SQL

SQL and PL/SQL Enhancements 1-19

Example of RIGHT OUTER Joins

SELECT e.last_name , d.department_nameFROM employees e RIGHT OUTER JOIN departments d

ON(e.department_id = d.department_id)

LAST_NAME DEPARTMENT_NAME------------------------- --------------------…Baer Public RelationsHiggens AccountingGietz Accounting

NOCManufacturingConstructionControl And Credit

Example of Right OUTER JoinsThis query retrieves all rows in the DEPARTMENTS table which is the right table even if there is no match in the EMPLOYEES tableThis query was completed in earlier releases as follows:SELECT e.last_name, d.department_name

FROM employees e, departments dWHERE e.department_id(+) = d.department_id

Page 20: 9ib_SQL

SQL and PL/SQL Enhancements 1-20

Example of FULL OUTER Joins

SELECT e.last_name , d.department_nameFROM employees e FULL OUTER JOIN departments dON(e.department_id = d.department_id)

LAST_NAME DEPARTMENT_NAME------------------------- --------------------…Greenberg FinanceGietz AccountingHiggens AccountingGrant

NOCManufacturingConstruction

Example of FULL OUTER JoinsThis query retrieves all rows in both tables regardless of whether there is a match in the other.It was not possible to complete this in earlier releases using outer joins. However we could accomplish the same result using the UNION operator as follows:SELECT e.last_name , d.department_nameFROM employees e, departments dWHERE e.department_id = d.department_id(+)UNIONSELECT e.last_name , d.department_nameFROM employees e, departments dWHERE e.department_id(+) = d.department_id;

Page 21: 9ib_SQL

SQL and PL/SQL Enhancements 1-21

Example of Using Subqueries

SELECT e.last_name , d.department_nameFROM employees e FULL OUTER JOIN departments dON(e.department_id = d.department_id)

AND d.location_id IN (SELECT l.location_id

FROM locations l ));

LAST_NAME DEPARTMENT_NAME------------------------- --------------------…Gietz AccountingHiggens AccountingGrant

NOCManufacturingConstruction

Example of Using SubqueriesIn the above example the EMPLOYEES table is full outer joined to DEPARTMENTS table which retrieves all matched as well as unmatched rows in both tables. Additionally through the use of a subquery the output is restricted to only those departments which contain locations for them. However because of the outer join NULL departments also show because of the presence of data in the employees table.

Page 22: 9ib_SQL

SQL and PL/SQL Enhancements 1-22

Example of Complex Join using Exists

SELECT department_name , cityFROM locations l JOIN departments d ON (l.location_id = d.location_id)AND NOT EXISTS (select 1 from employees e WHERE e.department_id IN d.department_id);

DEPARTMENT_NAME CITY------------------------------ ----------------------Treasury SeattleCorporate Tax SeattleControl And Credit Seattle…Retail Sales SeattleRecruiting SeattlePayroll Seattle

Example of Complex Join using ExistsIn the above example the departments and cities are retrieved by joining departments to locations based on the location_id column. However the output is restricted to those departments without employees in them all of which are in Seattle.

Page 23: 9ib_SQL

SQL and PL/SQL Enhancements 1-23

CASE Expressions in SQL: 1999

• SQL has the following types of CASE statements:– Simple CASE expression– Searched CASE expression– NULLIF– COALESCE

CASE Expressions in SQL: 1999The SQL: 1999 standard has four types of CASE Expressions:

Simple CASE expressionSearched CASE expressionsNULLIFCOALESCE

The simple CASE expression was available in Oracle 8.1.7. All the other expressions have been included in Oracle9i.Note: The CASE expression is supported in PL/SQL. For more information please refer to lesson 03 PL/SQL Enhancements

Page 24: 9ib_SQL

SQL and PL/SQL Enhancements 1-24

Simple CASE Expressions

• The simple CASE expression is similar to the DECODE function

• It can be used to search and replace values within a given expression

• For each searched value a return value can be specified

• Comparison operators are not allowed

Page 25: 9ib_SQL

SQL and PL/SQL Enhancements 1-25

Example of Simple CASE StatementIn the above example the department_id is evaluated to return the department_names. The ELSE keyword is used to specify an alternative if none of the conditions are matchedThe results of the above query are as follows:LAST_NAME Department Name------------------------- ---------------Whalen AdministrationHartstein MarketingGoyal MarketingRaphaely PurchasingKhoo PurchasingBaida PurchasingColmenares PurchasingHimuro PurchasingTobias PurchasingMarvis Human Resources…Grant N/A

SELECT last_name,

(CASE department_id

WHEN 10 THEN 'Administration'

WHEN 20 THEN 'Marketing'

WHEN 30 THEN 'Purchasing'

WHEN 40 THEN 'Human Resources'

ELSE 'N/A'

END) as "Department Names"

FROM employees

ORDER by department_id;

Example of Simple CASE Statement

Page 26: 9ib_SQL

SQL and PL/SQL Enhancements 1-26

Searched CASE Expressions

• The searched CASE expression is similar to an IF… THEN … ELSE construct

• It can be used to conditionally search and replace values within expressions

• Each WHEN condition can be different and multiple conditions can be combined with logical operators

• Comparison operators are allowed in the conditional expression

• Searched CASE expressions are more flexible than simple CASE expressions

Searched CASE Expressions

The searched CASE statement is very similar to an IF…THEN … ELSE construct. Each searched CASE statement can evaluate multiple conditions and each condition can reference different variables and operators. Multiple conditions may be combined through the use of logical operators. The searched CASE statement provides more flexible usage than the simple CASE statement

Page 27: 9ib_SQL

SQL and PL/SQL Enhancements 1-27

Example of Searched CASE StatementIn the above example we are trying to determine the raise for an employee based on job_id. If job_id is anything starting with "AD" then a raise of 10% is returned , for any job_id starting with "IT" a raise of 15% is returned and so on. The table raise is created as follows:

CREATE TABLE raise( name VARCHAR2(30), raise_pct VARCHAR2(10));

The contents of the table following the INSERT would be as follows:

SELECT * FROM raise;

NAME RAISE_PCT------------------------------ -----------------King 10%Kochhar 10%De Haan 10%…

INSERT INTO raise SELECT last_name,

CASEWHEN job_id LIKE 'AD%' THEN '10%'WHEN job_id LIKE 'IT%' THEN '15%'WHEN job_id LIKE 'PU%' THEN '18%'ELSE '20%'END

FROM employees

Example of Searched CASE Statement

Page 28: 9ib_SQL

SQL and PL/SQL Enhancements 1-28

SQL NULLIF and COALESCE

• The NULLIF function returns NULL if the first argument is equal to the second. Otherwise, the value of the first argument is returned.

• The COALESCE function is a generalization of Oracle’s NVL function

– Accepts any number of arguments– Returns the first NOT NULL argument

Page 29: 9ib_SQL

SQL and PL/SQL Enhancements 1-29

NULLIF and COALESCE

Both can be written as CASE expressions:

NULLIF(expr1,expr2) óCASE WHEN expr1 = expr2

THEN NULLELSE expr1

END CASE;

NULLIF(expr1,expr2) óCASE WHEN expr1 = expr2

THEN NULLELSE expr1

END CASE;

COALESCE(expr1,expr2,expr3,…) óCASE WHEN expr1 IS NOT NULL

THEN expr1ELSE COALESCE(expr2,expr3,…)

END CASE;

COALESCE(expr1,expr2,expr3,…) óCASE WHEN expr1 IS NOT NULL

THEN expr1ELSE COALESCE(expr2,expr3,…)

END CASE;

NULLIF And COALESECE EXPRESSIONSNULLIF expressionThe semantics of SQL NULLIF expression are defined by rewriting it asCASE

WHEN expression 1 = expression 2 THEN NULLELSE expression 1

END CASE;COALESCE ExpressionWhen a SQL COALESCE expression has exactly two arguments, the semantics are defined by rewriting it asCASEWHEN expression1 IS NOT NULL THEN expression 1ELSE expression 2

END CASE;When COALESCE has three or more arguments, it has the form COALESCE ( expression 1, expression 2, expression 3, . . ., expression n) the semantics are defined by rewriting it asCASEWHEN expression1 IS NOT NULL THEN expression 1ELSE COALESECE (expression2, expression3,. . .,expression n)

END CASE;

Page 30: 9ib_SQL

SQL and PL/SQL Enhancements 1-30

Example of SQL NULLIF expressionThe above example shows two queries. Query A retrieves employee_id's and their commission_pct s for all employees sorting by ascending order of commission pct. Query B retrieves employee_ids and the commission_pcts but the commission_pcts which are .1 are converted to NULLs.

SELECT employee_id, commission_pct comm1

FROM employees ORDER BY COMM;

Example of SQL NULLIF Expression

ID COMM1-------- -----

164 .1165 .1167 .1173 .1179 .1166 .1155 .15178 .15…

SELECT NULLIF (commission_pct,0.1)comm2 FROM employees

ORDER BY COMM;

ID COMM2-------- -----

164165167173179166155 .15178 .15

BBAA

Page 31: 9ib_SQL

SQL and PL/SQL Enhancements 1-31

SQL COALESCE expressionThe above example shows two queries. Query A retrieves employee last_names and the commission_pcts and shows that some employees are non commissioned employees, as the commission_pct is NULL. Query B retrieves the last_names and COALESCE commission_pct. The COALESCE function can only return like datatypes so therefore the commission_pct is first converted to a character expression and then COALESCED to return 'n/a'. The to_char conversion is not required if a numeric substitution value had been specified.The semantics of the above COALESCE operation is the same as

SELECT (CASE WHEN to_char(commission_pct) IS NOT NULL

THEN commission_pctELSE ' n/a'END ) comm2

FROM employees;

Example of SQL COALESCE Expression

SELECT last_name, commission_pct comm1

FROM employees;

LAST_NAME COMM1---------------- -----King Kochhar …Russell .4Partners .3…

SELECT last_name,COALESCE (to_char(commission_pct),'n/a')

comm2 FROM employees;

LAST_NAME COMM2--------------------- -----King n/aKochhar n/a …Russell .4Partners .3…

BBAA

Page 32: 9ib_SQL

SQL and PL/SQL Enhancements 1-32

Example of COALESCE with Multiple ExpressionsThe semantics of this query are the same as:SELECT last_name, ( CASE

WHEN commission_pct IS NOT NULL then commission_pctWHEN salary IS NOT NULL then salary…WHEN 10 IS NOT NULL then 10ELSE 0END) comm

FROM employees ORDER BY commission_pctThe above query returns the following output.

LAST_NAME COMM----------------------- -------------Marvins .1Tuvault .15…King 24000Kochhar 17000…

SELECT last_name, COALESCE

(commission_pct, salary, …, 10) comm FROM employees

ORDER BY commission_pct;

Example of COALESCE with Multiple Expressions

• The advantage of using COALESCE over the NVLfunction is that the COALESCE function can take multiple alternate vales

• If the first expression is NOT NULL then it returns that expression other wise it does a COALESCE of the remaining expressions. For example

Page 33: 9ib_SQL

SQL and PL/SQL Enhancements 1-33

Scalar Subqueries in SQL: 1999

• The scalar subquery is used to specify a scalar value derived from a query expression

• Scalar subqueries were supported in Oracle8ionly in the a limited set of cases :– VALUES list of an insert statement

– Arguments to a type constructor.• In Oracle9i scalar subqueries can be used in

the WHERE clause, SELECT list or in any place where a valid expression can be used.

• A scalar subquery can return only one value• The datatype of the return value matches the

value being selected in the subquery

Rules for scalar subqueriesThe rules for Scalar subqueries are:The degree of the scalar subquery is oneThe type of the scalar subquery is the type of the column of subqueryIf the cardinality of the scalar subquery is greater than 1, it results in an errorIf the cardinality of the scalar-subquery is 0, the value of the scalar subquery is NULLAssuming the cardinality to be 1, the value of the scalar subquery is the value of the column in the unique row of the subquery result.

Note: scalar query operations are very resource intensive and should be avoided if another type of query is available to retrieve the desired results.

Page 34: 9ib_SQL

SQL and PL/SQL Enhancements 1-34

Using Scalar Subqueries

Scalar subqueries can be used :• In all clauses of SELECT except GROUP BY• VALUES clause of INSERT statement• SET clause and WHERE clause of UPDATE

statement• In condition and expression part of DECODE

and CASE

Usage of Scalar SubqueriesScalar subqueries are not supported in

Default values for columnReturning clausesHash expressions for clustersFunctional Index ExpressionCheck Constraints on columnsWhen condition of triggersGroup by Clauses

Scalar subqueries may also negatively impact performance as they are as resource intensive as other forms of subqueries such as correlated subqueries.Note: The usage of scalar subqueries in SET clause of an UPDATE statement and VALUES list of an INSERT statement was supported in Oracle 8i itself.

Page 35: 9ib_SQL

SQL and PL/SQL Enhancements 1-35

Scalar Subqueries in SELECT List

The scalar subquery expression in Oracle SQL is extended to support subqueries as SELECTlist items. For example

SELECT employee_id, last_name, (SELECT department_name

FROM departments d WHERE e.department_id = d.department_id

) department_nameFROM employees eORDER BY department;

Scalar Subqueries in Oracle9iIn the above example employee_id, last Name and department names are retrieved by using a subquery in the select list for retrieving the department names from the departments table.The results of the above example are as follows:

EMPLOYEE_ID LAST_NAME DEPARTMENT_NAME----------- ------------- ------------------

205 Higgens Accounting206 Gietz Accounting200 Whalen Administration100 King Executive101 Kochhar Executive102 De Haan Executive103 Hunold IT104 Ernst IT107 Lorentz IT201 Hartstein Marketing202 Goyal Marketing

Page 36: 9ib_SQL

SQL and PL/SQL Enhancements 1-36

Scalar Subqueries in WHERE Clause

Scalar subqueries in Oracle SQL: 1999 can also be part of the WHERE clause condition. For example:

SELECT employee_id, last_nameFROM employees eWHERE ((SELECT location_id

FROM departments dWHERE e.department_id = d.department_id ) = (SELECT location_id

FROM locations lWHERE STATE_province =

'California') );

Scalar Subqueries in Oracle9iIn the above example we are retrieving the employee_ids and names of all employees located in California. The results of the above example is as as follows:

EMPLOYEE_ID LAST_NAME------------------ ---------------

124 Mourgos141 Rajs142 Davies143 Matos144 Vargas

…10 rows selected

Page 37: 9ib_SQL

SQL and PL/SQL Enhancements 1-37

Scalar Subqueries in ORDER BY Clause

Scalar Subqueries can now also be used in the ORDER BY clause. For example:

SELECT employee_id, last_nameFROM employees e

ORDER BY (select department_name from departments dwhere e.department_id = d.department_id);

Scalar Subqueries in Oracle9iIn the above example we are retrieving employee_ids and last names sorting the output by department_name. The results of the above example is as follows:

EMPLOYEE_ID LAST_NAME----------- -------------------------

205 Higgens206 Gietz200 Whalen100 King101 Kochhar102 De Haan103 Hunold104 Ernst107 Lorentz201 Hartstein202 Goyal

Page 38: 9ib_SQL

SQL and PL/SQL Enhancements 1-38

Scalar Subqueries in CASE Expressions

Scalar subqueries can be used in both the condition and the expression part of DECODE and CASE expressions . For example:

SELECT employee_id, last_name ,(CASE

WHEN department_id IN (SELECT department_id FROM departmentsWHERE location_id = 1800)

THEN 'Canada' ELSE 'other' END) locationFROM employees;

Scalar Subqueries in Oracle9iIn the above example we are retrieving the employee_id , last_name and locations of employees . For employees in location 1800 we display Canada and we display other for all others. The result of the above example is:

EMPLOYEE_ID LAST_NAME LOCATION--------------- --------------- ------------

100 King other101 Kochhar other102 De Haan other…….178 Grant other200 Whalen other201 Hartstein Canada202 Goyal Canada205 Higgens other206 Gietz other

Page 39: 9ib_SQL

SQL and PL/SQL Enhancements 1-39

Scalar Subqueries in Functions

Scalar Subqueries can be used as arguments to built in functions, user defined functions and type constructors. For example

SELECT last_name, SUBSTR ((SELECT department_name

FROM departments d WHERE d.department_id =e.department_id),

1, 10) departmentFROM employees e;

Scalar Subqueries in Oracle9iIn the above example we are retrieving the last names and the first 10 characters of the department name using the SUBSTR function on a subquery. The results of the above example is as follows:

LAST_NAME DEPARTMENT------------------ ----------------King ExecutiveKochhar ExecutiveDe Haan ExecutiveHunold ITErnst ITLorentz ITMourgos Shipping…

Page 40: 9ib_SQL

SQL and PL/SQL Enhancements 1-40

Overview of Explicit Defaults

• The explicit DEFAULT feature allows use of the DEFAULT keyword where the column default value is desired

• The addition of this feature is for compliance with the SQL:1999 Standard

• This allows the user to control where and when the DEFAULT value should be applied to data

• Explicit DEFAULT can be used in two types of statements: – INSERT statements - optional– UPDATE statements – mandatory for default

value to be applied• Another use of explicit DEFAULT is through

bind variables

Page 41: 9ib_SQL

SQL and PL/SQL Enhancements 1-41

Explicit DEFAULT

INSERT INTO employees (employee_id, first_name, department_id) VALUES (1, 'Scott', DEFAULT);

UPDATE employees SET department_id = DEFAULTWHERE department_id = 10;

CREATE TABLE EMPLOYEES (Employee_id NUMBER,Employee_name VARCHAR2(30),Department_id NUMBER(2) DEFAULT 20);

Explicit DefaultINSERT StatementsINSERT INTO employees(employee_id, first_name) VALUES (1, 'Scott ');

can be rewritten asINSERT INTO employees(employee_id, first_name, department_id) VA LUES

(1, 'Scott', DEFAULT);or we can simplify it toINSERT INTO employees VALUES (1, 'Scott', DEFAULT);

The second and third statements are much more clear since columns are explicitly specified to use default values.UPDATE StatementsIn UPDATE statement, we can set or change the DEFAULT value associated to a column. For example, the following statementUPDATE employees set department_id= DEFAULT where department_id = 10;replaces values of dept_id with the DEFAULT value in all rows where dept_id is 10.The DEFAULT keyword is may be left out of insert statements, but must be used in update statements if the default value is needed.Bind variablesThe following statement uses bind variable, :deptid from a host language. Using an indicator variable, the host language is able to specify the use of the DEFAULT value.

INSERT INTO employees VALUES (1, 'Scott', :deptid);

Page 42: 9ib_SQL

SQL and PL/SQL Enhancements 1-42

Benefits of Explicit Defaults

• Better data integrity is provided• Avoids "hard coding" of literals in applications• The explicit default is more user friendly and

provides a more flexible interface to users• The default value feature is compliant with

SQL: 1999 standard

Page 43: 9ib_SQL

SQL and PL/SQL Enhancements 1-43

Summary

In this lesson, you should have learned how to:• Create SQL: 1999 compliant joins• Create SQL CASE Statements

• Create scalar subqueries• Use explicit Defaults

Page 44: 9ib_SQL

SQL and PL/SQL Enhancements 2-1

SQL New Features in Oracle9i

Page 45: 9ib_SQL

SQL and PL/SQL Enhancements 2-2

Objectives

After completing this lesson you should beable to describe:• Constraint and Index enhancements• Globalization enhancement• Data warehousing features• Other enhancements

Page 46: 9ib_SQL

SQL and PL/SQL Enhancements 2-3

Overview of Constraint Enhancements

• Explicit control over the use of indexes by primary and unique keys

• Prevention of share lock on un-indexed foreign keys

• Enhancements to functional indexes

Page 47: 9ib_SQL

SQL and PL/SQL Enhancements 2-4

Applications of Constraint Enhancements

• The user has explicit control over how indexes are affected while creating or dropping unique and primary keys

• Improvement in the locking of un-indexed foreign keys during primary key updates

• Improvement in the look up of primary keys during foreign key insertion allows faster foreign key insertion

Page 48: 9ib_SQL

SQL and PL/SQL Enhancements 2-5

No Share Lock on Un-indexed Foreign KeysA table level share lock is placed on un-indexed foreign keys when doing an update or delete on the primary key, then the lock is released immediately after obtaining it. If multiple primary keys are updated or deleted, the lock is obtained and released once per row. The obtaining and releasing of the shared lock are coded as follows:• Get a savepoint• Obtain a share lock• Roll back to savepoint

No Share Lock on Un-indexed Foreign Keys

• A table level share lock is still placed on un-indexed foreign keys when doing an update or delete on the primary key

• However the lock is released immediately after obtaining it

Page 49: 9ib_SQL

SQL and PL/SQL Enhancements 2-6

Primary Key Look Up During Foreign Key CreationThe look up of matching primary keys at the time of foreign key insertion takes time. In release 9i of the Oracle database the first 256 primary keys can be cached so the addition of multiple foreign keys becomes significantly faster. The cache is only set for the second row processed . This avoids the overhead of setting up a cache for single row DML. The primary key cache supports rollback, in case the system rolls back to before a cached primary key was inserted. The primary key cache also deletes entries when the current statement deletes the primary key on disk.

Primary Key Look Up During Foreign Key Creation

• Primary keys are cached so the time taken for primary key look up is reduced

• Therefore the creation of foreign keys is faster• The cache is setup when the second foreign

key insert is processed

Page 50: 9ib_SQL

SQL and PL/SQL Enhancements 2-7

Example Of Creating Primary Key ConstraintIn the above example the CREATE INDEX clause is used in the CREATE TABLE statement to create a separate primary key index explicitly. The parallel and partition clauses can be used in this syntax to make index creation more efficient. The index can be a concatenated index.Example of Creating Unique ConstraintsCREATE TABLE departments(

department_id NUMBER(4) PRIMARY KEY ,department_name VARCHAR2(30),manager_id NUMBER(6),location_id NUMBER(4),CONSTRAINT depts_dname_uq UNIQUE(department_name,location_id)

USING INDEX (CREATE INDEX depts_dname_idx on departments(department_name, location_id)));

Example of Creating Primary Key Constraint

CREATE TABLE employees(employee_id NUMBER

PRIMARY KEY USING INDEX (CREATE INDEX employees_id_idx

ON employees(employee_id)),first_name VARCHAR2(15),last_name VARCHAR2(15),…);

Page 51: 9ib_SQL

SQL and PL/SQL Enhancements 2-8

Example of Dropping IndexesIn the above example the DROP INDEX and KEEP INDEX clauses are used to specify whether an indexes should be dropped or kept when primary or unique keys are dropped or disabled.Note: By default unique indexes which are implicitly created during the creation of primary and foreign keys are dropped when the unique or primary key constraints are dropped

Example of Dropping Indexes

ALTER TABLE departmentsDISABLE CONSTRAINT depts_dname_uq

CASCADE DROP INDEX;

ALTER TABLE employees DROP PRIMARY KEY KEEP INDEX;

Page 52: 9ib_SQL

SQL and PL/SQL Enhancements 2-9

Enhancements to Index Only scansIn prior releases Index-only scans could be done only when an index is known not to contain nulls. Expressions could not be marked NOT NULL. Function based indexes could not be used for index-only scans unless the query somehow disallowed nulls in the indexed expressions. The deduction of nulls in expressions based on the underlying columns in Oracle9i allows queries to do index only scans on functional indexes. All built in operators know whether their result is guaranteed to be not null when all their inputs are not null. Example

CREATE INDEX sal_comm_idx ON employees( salary*(1 + commission_pct)); -- this creates a functional index on the expression "salary*(1 + commission_pct)"

Consider the follwing query:SELECT salary*(1+commission_pct) AS total_comp FROM employees;

This query can do an index only scan on the functional index sal_comm_idx when both salary and commission_pct columns are NOT NULL.

Overview of Enhancements toFunctional Indexes

• The deduction of nulls in expressions based on the underlying columns in Oracle9i allows queries to do index only scans on functional indexes.

• All built in operators know whether their result is guaranteed to be NOT NULL when all their inputs are NOT NULL.

Page 53: 9ib_SQL

SQL and PL/SQL Enhancements 2-10

SQL Globalization Enhancements

• Unicode Enhancements• Date/Time Enhancements

REFERENCENote: for more information on these features in Oracle9i please refer to the Globalization module

Page 54: 9ib_SQL

SQL and PL/SQL Enhancements 2-11

Overview of Unicode Support

• In Oracle9i support for a reliable Unicode data type is accomplished through NCHAR.

• NCHAR, NVARCHAR2 and NCLOB are guaranteed to be Unicode encoded and always use code point length semantics.

• In Oracle9i it is possible to convert NCHAR to existing Oracle types such as:– CHAR– NUMBER– DATE– ROWID– CLOB

Overview of Unicode SupportThe primary requirement to improve interoperability is to provide implicit conversions between NCHAR and existing Oracle types, such as CHAR, NUMBER, DATE, ROWID and CLOB. The key difference between CHAR and NCHAR is different character encoding. For all the implicit conversions for CHAR/VARCHAR2 that are already supported, the same implicit conversion for NCHAR/NVARCHAR2 is supported in Oracle9i. In addition, the implicit conversion between CHAR/VARCHAR2 and NCHAR/NVARCHAR2 is supported as well.

Page 55: 9ib_SQL

SQL and PL/SQL Enhancements 2-12

Applications for Unicode Enhancements

• Strong demand for storing Unicode data in an Oracle database.

• Requirement for datatype which is guaranteed to be Unicode, encoded either in UTF8 or UTF16 and always uses code point length semantics.

• NCHAR data types allow character data in Unicode to be stored in a database regardless of character set.

• NCHAR makes the Oracle database server more flexible.

Applications For Unicode EnhancementsInternal and external Oracle customers deploying global applications have a strong demand for storing Unicode data in an Oracle database. Applications need a datatype which is guaranteed to be Unicode, encoded either in UTF8 or UTF16 and always uses code point length semantics, regardless of the database character set. NCHAR data types allow character data in Unicode to be stored in a database which may or may not use Unicode as the database character set.NCHAR makes the Oracle database server more flexible for users to select different character set encoding in one system and meet customers multi-lingual requirement.

Page 56: 9ib_SQL

SQL and PL/SQL Enhancements 2-13

Migrating to Oracle9i SQL NCHAR Datatypes

• In Oracle9i , the SQL NCHAR datatypes are limited to the Unicode character set encoding (UTF8 and AL16UTF16) only.

• Any other Oracle8 Server character sets that were available under the NCHAR datatype, including Asian character sets are no longer supported.

• For Oracle9i production, the migration utility also handles the upgrade from Pre-Oracle9i NCHAR to Unicode NCHAR

Migrating to Oracle9i SQL NCHAR DatatypeThe Oracle8i Server introduced a national character (NCHAR) datatype that allows for an alternate character set in addition to the original database character set. NCHAR supports a number of special, fixed-width Asian character sets that were introduced to provide for higher performance processing of Asian character data. In Oracle9i, the SQL NCHAR datatypes are limited to the Unicode character set encoding (UTF8 and AL16UTF16) only. Any other Oracle8 Server character sets that were available under the NCHAR datatype, including Asian character sets (for example, JA16SJISFIXED), are no longer supported. The migration path for existing NCHAR, NVARCHAR, and NCLOB columns is through export and import as follows: 1. Export all SQL NCHAR columns from Oracle8 2. Drop the SQL NCHAR columns

3. Upgrade database to Oracle9i4. Import the SQL NCHAR columns into Oracle9iFor Oracle9i production, the migration utility also handles the upgrade from Pre-Oracle9i NCHAR to Unicode NCHAR.

Page 57: 9ib_SQL

SQL and PL/SQL Enhancements 2-14

SQL Function Support for Implicit Type Conversion

• All SQL functions which take CHAR/VARCHAR2as arguments can take NCHAR/NVARCHAR2 as arguments

• SQL functions with multiple arguments of character type, can take arguments of any mixture of CHAR/VARCHAR2/NCHAR/NVARCHAR2.

SQL Function Support for Implicit Type ConversionAll the SQL functions which take CHAR/VARCHAR2 as arguments can also accept NCHAR/NVARCHAR2 as arguments. SQL function support of Unicode can be divided into 3 categories.

1. SQL functions with single character type arguments.2. SQL functions with multiple arguments of character types.The character arguments are either all CHAR or NCHAR same data type.

3. SQL functions with multiple arguments of character types.Some arguments are CHAR and some are NCHAR data type.

Categories 1 and 2 were already supported by Oracle. In Oracle9i, category 3 is supported so SQL functions can take arguments of any mixture of CHAR/VARCHAR2/NCHAR/NVARCHAR2.

Page 58: 9ib_SQL

SQL and PL/SQL Enhancements 2-15

Overview of Datetime Enhancements

• New Datetime datatypes have been introduced• New data type storage is available• Enhancements have been made to time zones

and local time zone

REFERENCE

Note:These Date/ Time features as well as others are covered in greater detail in the Globalization module

Page 59: 9ib_SQL

SQL and PL/SQL Enhancements 2-16

Datetime Datatypes

• TIMESTAMP • INTERVAL YEAR TO MONTH • INTERVAL DAY TO SECOND

Datetime DatatypesTIMESTAMPTIMESTAMP datatype allows the time to be stored as a date with fractional seconds. There are several variations of the datatype that we will see in the next few pages.INTERVAL YEAR TO MONTHThis datatype allows time to stored as an interval of years and monthsINTERVAL DAY TO SECONDThis datatype allows time to be stored as an interval of days to hours minutes and seconds

Page 60: 9ib_SQL

SQL and PL/SQL Enhancements 2-17

TIMESTAMP Datatype

• The TIMESTAMP datatype is an extension of the DATE datatype.

• It stores the year, month, and day of the DATE datatype, plus hour, minute, and second values as well as the fractional second value.

• The TIMESTAMP datatype is specified as follows:

TIMESTAMP[(fractional_seconds_precision)]

Datetime DatatypesNote: where fractional_seconds_precision optionally specifies the number of digits in the fractional part of the SECOND datetime field and can be a number in the range 0 to 9. The default is 6.ExampleCREATE TABLE new_employees

(employee_id NUMBER, first_name VARCHAR2(15),last_name VARCHAR2(15),…start_date TIMESTAMP(7),…);

In the above example we are creating a table NEW_EMPLOYEES with a column start_date with a datatype of TIMSTAMP. The precision of '7' indicates the fractional seconds precision which if not specified defaults to '6'.

Page 61: 9ib_SQL

SQL and PL/SQL Enhancements 2-18

Example of TIMESTAMP Datatype

SELECT hire_date FROM employees;

HIRE_DATE---------17-JUN-8721-SEP-8913-JAN-9303-JAN-9021-MAY-91…

ALTER TABLE employeesMODIFY hire_date TIMESTAMP;

SELECT hire_date FROM employees;HIRE_DATE----------------------------17-JUN-87 12.00.00.000000 AM21-SEP-89 12.00.00.000000 AM13-JAN-93 12.00.00.000000 AM03-JAN-90 12.00.00.000000 AM21-MAY-91 12.00.00.000000 AM…

A B

Example of TIMESTAMP DatatypeIn the above slide example A shows the data from the hire_date column of the employees table when the datatype of the column is DATE. In example B the table is altered and the datatype of the hire_date column is made into TIMESTAMP. The output shows the differences in display. IT is possible to convert from DATE to TIMESTAMP when the column has data , but it is not possible to convert from DATEor TIMESTAMP to TIMESTAMP WITH TIME ZONE unless the column is empty.

Page 62: 9ib_SQL

SQL and PL/SQL Enhancements 2-19

TIMESTAMP WITH TIME ZONE Datatype

• TIMESTAMP WITH TIME ZONE is a variant of TIMESTAMP that includes a time zone displacement in its value.

• The time zone displacement is the difference, in hours and minutes, between local time and UTC

• For example, you specify TIMESTAMP WITH TIME ZONE as a literal as follows:

TIMESTAMP '1997-01-31 09:26:56.66 +02:00'

TIMESTAMP[(fractional_seconds_precision)] WITH TIME ZONE

Datetime DatatypesUTC stand for Coordinated Universal Time— formerly Greenwich Mean Time. Two TIMESTAMP WITH TIME ZONE values are considered identical if they represent the same instant in UTC, regardless of the TIME ZONE offsets stored in the data. For example,TIMESTAMP '1999-04-15 8:00:00 -8:00'is the same asTIMESTAMP '1999-04-15 11:00:00 -5:00'That is, 8:00 a.m. Pacific Standard Time is the same as 11:00 a.m. Eastern Standard Time.This can also be specified asTIMESTAMP '1999-04-15 8:00:00 US/Pacific'Note: fractional_seconds_precision optionally specifies the number of digits in the fractional part of the SECOND datetime field and can be a number in the range 0 to 9. The default is 6.

Page 63: 9ib_SQL

SQL and PL/SQL Enhancements 2-20

Example of TIMESTAMP WITH TIME ZONE

CREATE TABLE new_orders as (order_date TIMESTAMP WITH TIME ZONE;

INSERT INTO new_orders SELECT SYSDATE FROM DUAL;

SELECT * FROM new_orders;order_date---------------------------------------------------17-JAN-01 10.00.00.000000 AM -08:00

Example of TIMESTAMP WITH TIME ZONEIn the above example a new table new_orders is created with a column of datatype TIMESTAMP WITH TIME ZONE. This table is populated by selecting the SYSDATE from DUAL table. The output from the new_orders table shows the offset from UTC which is –8 hours for all these records. Note that even though SYSDATE is of type DATE, it automatically gets converted to TIMESTAMP WITH TIME ZONE through the INSERT

Page 64: 9ib_SQL

SQL and PL/SQL Enhancements 2-21

TIMESTAMP WITH LOCAL TIME Datatype

• TIMESTAMP WITH LOCAL TIME ZONE is another variant of TIMESTAMP that includes a time zone displacement in its value.

• Data stored in the database is normalized to the database time zone

• The time zone displacement is not stored as part of the column data

• Oracle returns the data in the users' local session time zone.

• TIMESTAMP WITH LOCAL TIME ZONE datatype is specified as follows:

TIMESTAMP[(fractional_seconds_precision)] WITH LOCAL TIME ZONE

Datetime DatatypesUnlike TIMESTAMP WITH TIME ZONE, you can specify columns of type TIMESTAMP WITH LOCAL TIME ZONE as part of a primary or unique key. The time zone displacement is the difference (in hours and minutes) between local time and UTC. There is no literal for TIMESTAMP WITH LOCAL TIME ZONE .Note: fractional_seconds_precision optionally specifies the number of digits in the fractional part of the SECOND datetime field and can be a number in the range 0 to 9. The default is 6.

Page 65: 9ib_SQL

SQL and PL/SQL Enhancements 2-22

Example of TIMESTAMP WITH TIME ZONE

CREATE TABLE new_orders as (order_date TIMESTAMP WITH LOCAL TIME ZONE;

INSERT INTO new_orders VALUES('15-NOV-00 09:34:28 AM');

SELECT * FROM new_orders;order_date---------------------15-NOV-00 09.34.28 AM

ALTER SESSION SET TIME_ZONE = 'EUROPE/LONDON';SELECT * FROM new_orders;order_date ---------------------15-NOV-00 02.34.28 PM

Example of TIMESTAMP WITH TIME ZONEIn the above example a new table new_orders is created with a column of datatype TIMESTAMP WITH LOCAL TIME ZONE. This table is populated by inserting a record into it. The output from the new_orders table shows that the data is stored without the timezone offset. Then the ALTER SESSIONcommand is issued to change the time zone of the local session. A second query on the same table now reflects the data with the local time zone reflected in the time value.

Page 66: 9ib_SQL

SQL and PL/SQL Enhancements 2-23

INTERVAL YEAR TO MONTH Datatype

• INTERVAL YEAR TO MONTH stores a period of time using the YEAR and MONTHdatetime fields.

• For Example:

INTERVAL YEAR [(year_precision)] TO MONTH

INTERVAL '312-2' YEAR(3) TO MONTHIndicates an interval of 312 years and 2 months

INTERVAL '312' YEAR(3)Indicates 312 years and 0 months

INTERVAL '300' MONTH(3)Indicates an interval of 300 months

INTERVAL YEAR TO MONTH DatatypeINTERVAL YEAR TO MONTH stores a period of time using the YEAR and MONTHdatetime fields. Specify INTERVAL YEAR TO MONTH as follows:INTERVAL YEAR [(year_precision)] TO MONTHwhere year_precision is the number of digits in the YEAR datetime field. The default value of year_precision is 2.Restriction: The leading field must be more significant than the trailing field. For example, INTERVAL '0-1' MONTH TO YEAR is not valid.

Page 67: 9ib_SQL

SQL and PL/SQL Enhancements 2-24

TIME_ZONE Session Parameter

• TIME_ZONE may be set to

– O/S Local Time Zone– An absolute offset– Database Time Zone– A named region

ALTER SESSION SET TIME_ZONE = '-05:00';ALTER SESSION SET TIME_ZONE = dbtimezone;ALTER SESSION SET TIME_ZONE = local;ALTER SESSION SET TIME_ZONE = 'America/New_York';

ALTER SESSION SET TIME_ZONE = '-05:00';ALTER SESSION SET TIME_ZONE = dbtimezone;ALTER SESSION SET TIME_ZONE = local;ALTER SESSION SET TIME_ZONE = 'America/New_York';

TIME_ZONE Session ParameterThe surface of the earth is divided into zones, called time zones, in which every correct clocktells the same time, known as local time. Local time is equal to UTC (Coordinated UniversalTime, previously called Greenwich mean time, or GMT) plus the time zone displacement,which is a value of INTERVAL HOUR TO MINUTE, between -'12:59' and +'13:00'. The above examples show how we can use the ALTER SESSION command to change the session time zone values. We will be using this command in the subsequent slides. The dictionary view V$TIMEZONE_NAMES gives all acceptable values for time zone names.

Page 68: 9ib_SQL

SQL and PL/SQL Enhancements 2-25

Datetime Functions

• CURRENT_DATE • CURRENT_TIMESTAMP • LOCALTIMESTAMP • DBTIMEZONE• FROM_TZ • SESSIONTIMEZONE • TO_YMINTERVAL• TO_TIMESTAMP• TO_TIMESTAMP_TZ• TZ_OFFSET • EXTRACT

Datetime FunctionsCURRENT_DATE returns the current date in the session time zone, in a value in the Gregorian calendar of datatype DATE.CURRENT_TIMESTAMP returns the current date and time in the session time zone, in a value of datatype TIMESTAMP WITH TIME ZONE.The LOCALTIMESTAMP function returns the current date and time in the session time zone in a value of datatype TIMESTAMP.The DBTIMEZONE function returns the value of the database time zone.The FROM_TZ function converts a timestamp value at a time zone to a TIMESTAMP WITH TIME ZONE value.The SESSIONTIMEZONE function returns the value of the current session's time zone.TO_DSINTERVAL converts a character string of CHAR, VARCHAR2, NCHAR, or NVARCHAR2 datatype to an INTERVAL DAY TO SECOND type.The TO_YMINTERVAL function converts a character string of CHAR, VARCHAR2, NCHAR, or NVARCHAR2 datatype to an INTERVAL YEAR TO MONTH type.TO_TIMESTAMP converts a value of CHAR, VARCHAR2, NCHAR,or NVARCHAR2 datatype to a value of TIMESTAMP datatypeTO_TIMESTAMP_TZ is similar to TO_TIMESTAMP . It returns TO_TIMESTAMP as well as the time zone valueTZ_OFFSET returns the time zone offset corresponding to the value entered based on the date the statement is executed.An EXTRACT expression extracts and returns the value of a specified datetime field from a datetime or interval value expression.

Page 69: 9ib_SQL

SQL and PL/SQL Enhancements 2-26

CURRENT_DATE , CURRENT_TIMESTAMPand LOCAL_TIMESTAMP

• CURRENT_DATE

– returns the current date from the system– Has a datatype of DATE

• CURRENT_TIMESTAMP

– Returns the current timestamp from the system

– Has a datatype of TIMESTAMP WITH TIME ZONE

• LOCAL_TIMESTAMP

– Returns the current timestamp from user session

– Has a datatype of TIMESTAMP WITH TIME ZONE

CURRENT_DATE, CURRENT_TIMESTAMP and LOCAL_TIMESTAMP

Oracle9i supports the datetime value functions CURRENT_DATE, CURRENT_TIME, and CURRENT_TIMESTAMP, which respectively return the current date, current time, and current timestamp. The data type of CURRENT_DATE is DATE. The data type of CURRENT_TIME is TIME WITH TIME ZONE. The data type of CURRENT_TIMESTAMP is TIMESTAMP WITH TIME ZONE. The time and timestamp values are returned with time zone displacement equal to the current time zone displacement of the SQL session. If an SQL statement causes the evaluation of one or more datetime value functions, then all such evaluations are effectively performed simultaneously. These functions are NLS sensitive, that is, the results will be in the current NLS calendar and datetime formats.CURRENT_TIME and CURRENT_TIMESTAMP have optional argument to specify the precision of the time and timestamp value returned. The LOCALTIMESTAMP function returns the current date and time in the session time zone in a value of datatype TIMESTAMP. The difference between this function and CURRENT_TIMESTAMP is that LOCALTIMESTAMP returns a TIMESTAMP value while CURRENT_TIMESTAMP returns a TIMESTAMP WITH TIME ZONE value.

Page 70: 9ib_SQL

SQL and PL/SQL Enhancements 2-27

Example of CURRENT_DATE

ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY H24:MI:SS';ALTER SESSION SET TIME_ZONE = '-5:0';SELECT SESSIONTIMEZONE, CURRENT_DATE FROM DUAL;SESSION CURRENT_DATE------- ---------------------05:00 04-APR-2000 13:14:03

ALTER SESSION SET TIME_ZONE = '-8:0';SELECT SESSIONTIMEZONE, CURRENT_DATE FROM DUAL;SESSION CURRENT_DATE------- ---------------------08:00 04-APR-2000 10:14:33

Example of CURRENT_DATECURRENT_DATE returns the current date in the session time zone, in a value in the Gregorian calendar of datatype DATE. CURRENT_DATE is very similar to the SYSDATE function available in earlier releases. However changes to time zones are reflected in the current_date. In the above examples the value of CURRENT_DATE is retrieved from dual for two different time zones by issuing the ALTER SESSION command. The outputs show the change reflected in the time value.

Page 71: 9ib_SQL

SQL and PL/SQL Enhancements 2-28

Example of CURRENT_TIMESTAMP

ALTER SESSION SET TIME_ZONE = '-07:00';

SELECT SESSIONTIMEZONE,CURRENT_TIMESTAMP FROM DUAL;SESSION CURRENT_TIMESTAMP------- -----------------------------------07:00 19-SEP-2000 15:38:10.331911 -07:00

ALTER SESSION SET TIME_ZONE = '-04:00';

SELECT SESSIONTIMEZONE,CURRENT_TIMESTAMP FROM DUAL;SESSION CURRENT_TIMESTAMP------- -----------------------------------04:00 19-SEP-2000 18:38:10.331911 -04:00

Example of CURRENT_TIMESTAMPCURRENT_TIMESTAMP returns the current date and time in the session time zone, in a value of datatype TIMESTAMP WITH TIME ZONE. The time zone displacement reflects the current local time of the SQL session. The difference between this function and LOCAL TIMESTAMP is that CURRENT_TIMESTAMP returns a TIMESTAMP WITH TIME ZONE value while LOCALTIMESTAMP returns a TIMESTAMP value. In the above examples the value of CURRENT_TIMESTAMP is retrieved from dual for two different time zones by issuing the ALTER SESSION command. The outputs show the change reflected in the time value.

Page 72: 9ib_SQL

SQL and PL/SQL Enhancements 2-29

Example of LOCALTIMESTAMP

ALTER SESSION SET TIME_ZONE = '-8:00';

SELECT CURRENT_TIMESTAMP, LOCALTIMESTAMP FROM DUAL;

CURRENT_TIMESTAMP LOCALTIMESTAMP-------------------------------- -------------------------19-SEP-00 11:54:25.655551 -08:00 19-SEP-00 11:54:25.655551

ALTER SESSION SET TIME_ZONE = '-5:00';

SELECT CURRENT_TIMESTAMP, LOCALTIMESTAMP FROM DUAL;

CURRENT_TIMESTAMP LOCALTIMESTAMP-------------------------------- -------------------------19-SEP-00 14:54:25.676207 -05:00 19-SEP-00 14:54:25.676207

LOCALTIMESTAMPThe LOCALTIMESTAMP function returns the current date and time in the session time zone in a value of datatype TIMESTAMP. The difference between this function and CURRENT_TIMESTAMP is thatLOCALTIMESTAMP returns a TIMESTAMP value while CURRENT_TIMESTAMP returns a TIMESTAMP WITH TIME ZONE value. In the above examples the value of CURRENT_TIMESTAMP is compared with the value of LOCALTIMESTAMP retrieved from dual for two different time zones by issuing the ALTER SESSION command. The outputs show the change reflected in the time value. The CURRENT_TIMESTAMP shows the time zone displacement while the LOCALTIMESTAMP does not.

Page 73: 9ib_SQL

SQL and PL/SQL Enhancements 2-30

Example of DBTIMEZONE

SELECT DBTIMEZONE FROM DUAL;DBTIMEZ-------+00:00

DBTIMEZONE– Returns the value of the database time zone

DBTIMEZONEThe DBTIMEZONE function returns the value of the database time zone. The return type is a time zone offset or a time zone region name, depending on how the user specified the database time zone value in the most recent CREATE DATABASE or ALTER DATABASE statement.

Page 74: 9ib_SQL

SQL and PL/SQL Enhancements 2-31

Example of Using FROM_TZ

SELECT FROM_TZ(TIMESTAMP '2000-03-28 08:00:00', '3:00')

FROM DUAL;

FROM_TZ(TIMESTAMP '2000-03-2808:00:00','3:00')---------------------------------------------28-MAR-00 08.00.00 AM +03:00

• FROM_TZ– Converts a timestamp value at a time zone to a

TIMESTAMP WITH TIME ZONE value

FROM_TZThe FROM_TZ function converts a timestamp value at a time zone to a TIMESTAMP WITH TIME ZONE value. In the above example the FROM_TZ function accepts a literal and converts it to a TIMESTAMP value. The first argument is the TIMESTAMP value and the second argument is the time zone offset. In the above example the literal TIMESTAMP '2000-03-28 08:00:00', '3:00' is converted to a TIMESTAMP WITH TIME ZONE value 28-MAR-00 08.00.00 AM +03:00

Page 75: 9ib_SQL

SQL and PL/SQL Enhancements 2-32

Examples of SESSIONTIMEZONE

SELECT SESSIONTIMEZONE FROM DUAL;

SESSION--------05:00

ALTER SESSION SET TIME_ZONE = 'US/PACIFIC';

SELECT SESSIONTIMEZONE FROM DUAL;

SESSIONTIMEZONE-----------------US/Pacific

• SESSIONTIMEZONE– Returns the value of the current session’s time zone

SESSIONTIMEZONEThe SESSIONTIMEZONE function returns the value of the current session's time zone. The return type is a time zone offset or a time zone region name, depending on how the user specified the session time zone value in the most recent ALTER SESSION statement. In the above example we first retrieve the SESSIONTIME zone value from DUAL and it indicates the current value for the sessions timezone. Then we issue an ALTER SESSION command and change the time zone to 'US/PACIFIC'. Now when we retrieve the SESSIONTIMEZONE from DUAL we get 'US/PACIFIC' which was the last set value for this session.

Page 76: 9ib_SQL

SQL and PL/SQL Enhancements 2-33

Example of Using TO_DSINTERVAL

SELECT last_name, hire_date, hire_date + TO_DSINTERVAL('100 10:00:00') hiredate2FROM employees;LAST_NAME HIRE_DATE HIREDATE2------------------------- --------- ---------King 17-JUN-87 25-SEP-87Kochhar 21-SEP-89 30-DEC-89De Haan 13-JAN-93 23-APR-93Hunold 03-JAN-90 13-APR-90…

• TO_DSINTERVAL

– Converts a character string to an INTERVAL DAY TO SECOND datatype

TO_DSINTERVALTO_DSINTERVAL converts a character string of CHAR, VARCHAR2, NCHAR, or NVARCHAR2datatype to an INTERVAL DAY TO SECOND type.

In the above example the date 100 days and 10 hrs after the hire date is obtained

Page 77: 9ib_SQL

SQL and PL/SQL Enhancements 2-34

Example of Using TO_YMININTERVAL

SELECT hire_date, hire_date + TO_YMINTERVAL('01-02') ytmFROM employees;

HIRE_DATE YTM--------- ---------17-JUN-87 17-AUG-8821-SEP-89 21-NOV-9013-JAN-93 13-MAR-9403-JAN-90 03-MAR-9121-MAY-91 21-JUL-92…

• TO_YMINTERVAL

– Converts a character string to an INTERVAL YEAR TO MONTH datatype

TO_YMINTERVALThe TO_YMINTERVAL function converts a character string of CHAR, VARCHAR2, NCHAR, or NVARCHAR2 datatype to an INTERVAL YEAR TO MONTH type.

In the above example the date 1 year and 2 months after the hire date is obtained

Page 78: 9ib_SQL

SQL and PL/SQL Enhancements 2-35

Example of TO_TIMESTAMP and TO_TIMESTAMPTZ

Example of TO_TIMESTAMP

SELECT TO_TIMESTAMP('1999-12-01 11:00:00','YYYY-MM-DD HH:MI:SS') Timestamp

FROM DUAL;

TIMESTAMP-------------------------------01-DEC-99 11.00.00.000000000 AM

• TO_TIMESTAMP– Converts char of CHAR or VARCHAR2 datatype to a value of

TIMESTAMP datatype

TO_TIMESTAMPTO_TIMESTAMP converts a value of CHAR, VARCHAR2, NCHAR,or NVARCHAR2 datatype to a value of TIMESTAMP datatype. It is very similar to the TO_DATE function in that it accepts a literal as the first argument and the input format as the second argument. It returns the value converted to a timestamp. In the above example the the literal '1999-12-01 11:00:00', 'YYYY-MM-DD HH:MI:SS' is converted first to a TIMESTAMP using TO_TIMESTAMP and in the next example to a TIMESTAMP WITH TIME ZONE using TO_TIMESTAMP_TZ. The value '1999-12-01 11:00:00' is the actual value to be converted. The value 'YYYY-MM-DD HH:MI:SS' specifies the input format.The output is formatted to the default format for TIMESTAMP in the database.Example of TO_TIMESTAMP_TZ

SELECT TO_TIMESTAMP_TZ('1999-12-01 11:00:00 -8:00','YYYY-MM-DD HH:MI:SS TZH:TZM') TIMESTAMPTZ

FROM DUAL;

TIMESTAMPTZ--------------------------------------01-DEC-99 11.00.00.000000000 AM -08:00

Page 79: 9ib_SQL

SQL and PL/SQL Enhancements 2-36

Example of TZ_OFFSET

SELECT TZ_OFFSET('US/Eastern') FROM DUAL;TZ_OFFS--------04:00

TZ_OFFSET

– returns the offset from the session time zone for a specified time zone value

TZ_OFFSETTZ_OFFSET returns the time zone offset corresponding to the value entered based on the date the statement is executed. In the above example the offset for 'US/Eastern' from the session time zone is returned.

Page 80: 9ib_SQL

SQL and PL/SQL Enhancements 2-37

Example of Using EXTRACT

SELECT EXTRACT(YEAR FROM DATE '1998-09-20')YEARFROM DUAL;

YEAR-------

1998

SELECT EXTRACT(MONTH FROM DATE '1998-09-20')YEARFROM DUAL

YEAR-----

9

• EXTRACT– Extracts values from Datetime and Interval– Extracting from Datetime with time zone returns value in

UTC

EXTRACT Datetime ExpressionAn EXTRACT expression extracts and returns the value of a specified datetime field from a datetime or interval value expression. When you extract a TIMEZONE_REGION or TIMEZONE_ABBR(abbreviation), the value returned is a string containing the appropriate time zone name or abbreviation. When you extract any of the other values, the value returned is in the Gregorian calendar. When extracting from a datetime with a time zone value, the value returned is in UTC. In the above examples we extract first the year and then the month from the literal '1998-09-20'.

Page 81: 9ib_SQL

SQL and PL/SQL Enhancements 2-38

REFERENCE

Note: These Data Warehousing features as well as others are covered in greater detail in the Business Intelligence moduleNote: Table functions are discussed under the Extensibility lesson in the extensibility module and in the PL/SQL lesson in the SQL&PL/SQL module

Data Warehousing Enhancements in Oracle9i

• Multi-table INSERT statements

• Using external tables• MERGE statements

• Table Functions

Page 82: 9ib_SQL

SQL and PL/SQL Enhancements 2-39

Overview of Multi-table Insert Statements

• Allows the INSERT…SELECT statement to insert rows into multiple tables as part of a single DML statement

• Can be used in data warehousing systems to transfer data from one or more operational sources to a set of target tables

• Can be used for refreshing materialized views

Overview of Multi-table InsertsThe INSERT … SELECT statement with the new syntax can be parallelized and used with the direct-load mechanism. The multi table INSERT statement inserts computed rows derived from the rows returned from the evaluation of a subquery. There are two forms of the multi-table INSERTstatement: unconditional and conditional. For the unconditional form, an INTO clause list is executed once for each row returned by the subquery. For the conditional form INTO clause lists are guarded by WHEN clauses that determine whether the corresponding INTO clause list is executed.

• An INTO clause list consists of one or more INTO clauses . The execution of an INTO clause list causes the insertion of one row for each INTO clause in the list.

• An INTO clause specifies the target into which a computed row is inserted . The target specified may be any table expression that is legal for an INSERT … SELECT statement. However aliases cannot be used. The same table may be specified as the target for more than one INTO clause.

• An INTO clause also provides the value of the row to be inserted using a VALUES clause . An expression used in the VALUES clause can be any legal expression , but may only refer to columns returned by the select list of the subquery. If the VALUES clause is omitted , the select list of the subquery provides the values to be inserted. If a column list is given, each column in the list is assigned a corresponding value from the VALUES clause or the subquery. If no column list is given , the computed row must provide values for all columns in the target table.

Page 83: 9ib_SQL

SQL and PL/SQL Enhancements 2-40

Types of Multi-table INSERT Statements

Unconditional INSERTThis allows inserts into multiple tables from the same sub query. All INSERT statements will execute

simultaneously.Pivoting INSERTThis allows inserting into the same table several times using the same subquery as the source.Conditional ALL INSERTThis allows inserts into multiple tables based on certain condition s being satisfied. All INSERTS which

satisfy the condition will be executedConditional FIRST INSERTThis allows only one INSERT which is the first to satisfy a condition to be executed. All subsequent

inserts will be ignored.

Note: This feature is an Oracle extension to SQL and is not a SQL: 1999 standard.

Types of Multi-table INSERT Statements

• Unconditional INSERT• Pivoting INSERT• Conditional ALL INSERT• Conditional FIRST INSERT

Page 84: 9ib_SQL

SQL and PL/SQL Enhancements 2-41

Example of Unconditional INSERT

INSERT ALLINTO product_activity VALUES(today, product_id, quantity)INTO product_sales VALUES(today, product_id, total)SELECT TRUNC(order_date) today, product_id,

SUM(unit_price) total, SUM(quantity) quantityFROM orders, order_items

WHERE orders.order_id = order_items.order_id AND order_date = TRUNC(SYSDATE)

GROUP BY product_id;

Exemple of Unconditional INSERTThis allows inserts into multiple tables from the same sub query. All INSERT statements will execute simultaneously.ALL into_clause:Specify ALL followed by multiple insert_into_clauses to perform an unconditional multi table insert. Oracle executes each insert_into_clause once for each row returned by the subquery.In the above example we are inserting into both the PRODUCT_ACTIVITY and PRODUCT _SALEStables retrieving from the orders and order_items tables. Both tables will be populated simultaneously.

Page 85: 9ib_SQL

SQL and PL/SQL Enhancements 2-42

Example of Pivoting INSERT

INSERT ALLINTO sales VALUES (product_id,

TO_DATE(week_id, 'WW'), sales_sun)INTO sales VALUES (product_id,

TO_DATE(week_id, 'WW'), sales_mon)INTO sales VALUES (product_id,

TO_DATE(week_id, 'WW'), sales_tue)INTO sales VALUES (product_id,

TO_DATE(week_id, 'WW'), sales_wed)INTO sales VALUES (product_id,

TO_DATE(week_id, 'WW'), sales_thu)…

Pivoting INSERTThe above slide is an example of inserting into the same table several times pivoting from a non-normalized form to a normalized form. We are retrieving the weekly sales information from SALES_SOURCE_DELTA table and using this information to insert the daily sales values into the sales table.

Page 86: 9ib_SQL

SQL and PL/SQL Enhancements 2-43

Example of Pivoting INSERT (continued)

…INTO sales VALUES (product_id,

TO_DATE(week_id, 'WW'), sales_fri)INTO sales VALUES (product_id,

TO_DATE(week_id, 'WW'), sales_sat)SELECT product_id, week_id, sales_sun, sales_mon, sales_tue, sales_wed, sales_thu,

sales_fri, sales_satFROM sales_source_data;

Example of Pivoting INSERTThis is continuation of the example in the previous slide

Page 87: 9ib_SQL

SQL and PL/SQL Enhancements 2-44

Syntax for Conditional ALL INSERT

INSERT ALLWHEN product_id IN (select product_id

from promotional_items)INTO promotional_sales VALUES

(product_id, list_price)WHEN order_mode = 'online'

INTO web_orders VALUES (product_id, order_total)

SELECT product_id, list_price, order_total,order_mode

FROM orders;

Syntax for Conditional ALL INSERTThis allows inserts into multiple tables based on certain condition s being satisfied. All INSERTs which satisfy the condition will be executedThe above example inserts a row into the PROMOTIONAL_SALES table for products sold that are on the promotional list, and into the WEB_ORDERS table for products for which online orders were used. It is possible that two rows are inserted for some item lines, and none for others.

Page 88: 9ib_SQL

SQL and PL/SQL Enhancements 2-45

Syntax for Conditional FIRST INSERT

INSERT FIRSTWHEN order_total> 10000 THENINTO priority_handling VALUES (id)

WHEN order_total > 5000 THENINTO special_handling VALUES (id)

WHEN total > 3000 THENINTO privilege_handling VALUES (id)

ELSEINTO regular_handling VALUES (id)SELECT order_total , order_id id

FROM orders ;

Syntax for Conditional FIRST INSERTThis allows only one INSERT which is the first to satisfy a condition to be executed. All subsequent inserts will be ignored.The above statement inserts into an appropriate handling according to the total of an order. If you specify FIRST as in the above example, Oracle evaluates each WHEN clause in the order in which it appears in the statement. For the first WHEN clause that evaluates to true, Oracle executes the corresponding INTO clause and skips subsequent WHEN clauses for the given row.For a given row, if no WHEN clause evaluates to true:•If you have specified an ELSE clause Oracle executes the INTO clause list associated with the ELSEclause.•If you did not specify an ELSE clause, Oracle takes no action for that row.

Page 89: 9ib_SQL

SQL and PL/SQL Enhancements 2-46

Advantages of Multi-table INSERTsThe multi table INSERT statement gives us the ability to simultaneously insert into several tables using only on sub query as the data source. It allows the use of the conditional WHEN clause to do conditional INSERTs. It is very flexible and allows different types of INSERTs both into the same table as well as multiple tables. Plus it is a major performance benefit at it reduces the need for multiple scans on the source data.

Advantages of Multi-table INSERTs

• Eliminates the need for multiple INSERT.. SELECT statements to populate multiple tables

• Eliminates the need for a procedure to do multiple INSERTs using IF.. THEN syntax

• Significant performance improvement over above two methods due to the elimination of the cost of materialization and repeated scans on the source data

Page 90: 9ib_SQL

SQL and PL/SQL Enhancements 2-47

Overview of MERGE statementsMERGE statements allow the conditional INSERT or UPDATE of information into a table. MERGEstatements will try to do a join between the source and the destination tables based on a given join condition. If a match is found then the MERGE does an update of existing rows. If no matches are found then the MERGE completes an INSERT of new records into the table.

They are included in the Oracle9i database to satisfy SQL:!999 compliance. They are also know as UPSERT statements ion other databases.

Overview of MERGE statements

• MERGE statements

– provide the ability to conditionally UPDATE/INSERT into the database

– Do an UPDATE if the row exists and an INSERT if it is a new row

– Avoid multiple updates– Can be used in Data Warehousing

applications

Page 91: 9ib_SQL

SQL and PL/SQL Enhancements 2-48

Applications of MERGE statementsMERGE statements use a single SQL statement to complete and UPDATE or INSERT or both. Since there is only call to the database this significantly improves performance.Additionally the statement can be parallelized transparently and bulk DML can be used. It also eliminates the need for a program to conditionally evaluate the need for the INSERT or UPDATE. Performance is improved because fewer statements require fewer scans of the source tables

Applications of MERGE statements

• MERGE statements use a single SQL statement to complete and UPDATE or INSERT or both

• The statement can be parallelized transparently

• Bulk DML can be used• Performance is improved because fewer

statements require fewer scans of the source tables

Page 92: 9ib_SQL

SQL and PL/SQL Enhancements 2-49

Example of Using the MERGE Statement in Data Warehousing

MERGE INTO customer CUSING cust_src S

ON (c.customer_id = s.src_customer_id)WHEN MATCHED THENUPDATE SET c.cust_address = s.cust_address

WHEN NOT MATCHED THENINSERT ( Customer_id, cust_first_name,…)

VALUES (src_customer_id, src_first_name,…);

Example of MERGEThis an example of using MERGE in data warehousing. Customer(C) is a large fact table and cust_src is a smaller "delta" table with rows which need to be inserted into customer conditionally. This MERGE statement indicates that table customer has to be MERGEed with the rows returned from the evaluation of the ON clause of the MERGE. The ON clause in this case is the table cust_src (S), but it can be an arbitrary query. Each row from S is checked for a match to any row in C by satisfying the join condition specified by the On clause. If so, each row in C is updated using the UPDATE SETclause of the MERGE statement. If no such row exists in C then the rows are inserted into table Causing the ELSE INSERT clause.

Page 93: 9ib_SQL

SQL and PL/SQL Enhancements 2-50

Overview of External Tables

• External tables are read-only tables where the data is stored outside the database in flat files

• The data can be queried using SQL but no DML is allowed and no indexes can be created

• The metadata for an external table is created using a CREATE TABLE statement

• With the help of external tables Oracle data can be stored as flat files

• An external table describes how the external data should be presented to the database

Overview of External TablesExternal tables are like regular SQL tables with the exception that the data is read only and does not reside in the database, thus the organization is external. The external table can be queried directly and in parallel using SQL. As a result , the external table acts as a view The metadata for the external table is created using the "CREATE TABLE . . ORGANIZATION EXTERNAL" statement.No DML operations are possible and no indexes can be created on them. The CREATE TABLE . . ORGANIZATION EXTERNAL operation involves only the creation of metadata in the Oracle Dictionary since the external data already exists outside the database. Once the metadata is created, the external table feature enables the user to easily perform parallel extraction of data from the specified external sources.

REFERENCENote: External tables and MERGES are covered in greater detail in the Business Intelligence module

Page 94: 9ib_SQL

SQL and PL/SQL Enhancements 2-51

Applications of External Tables

External tables :• Allow external data to be queried and joined

directly and in parallel without requiring it to be loaded into the database.

• Eliminate the need for staging the data within the database for ETL in data warehousing applications

• Are useful in environments where an external source has to be joined with database objects and then transformed

• Are useful when the external data is large and not queried frequently

Applications of External TablesOracle9i‘s external table feature allows you to use external data as a “virtual table”and can be queried and joined directly and in parallel without requiring the external data to be first loaded in the database.External tables enable the pipelining of the loading phase with the transformation phase. The transformation process can be merged with the loading process without any interruption of the data streaming. It is no longer necessary to stage the data inside the database for comparison or transformation.The main difference between external tables and regular tables is that externally organized tables are read-only. No DML operations are possible and no indexes can be created on them. In Oracle9i external tables are a complement to the existing SQL*Loader functionality, and are especially useful for environments where the complete external source has to be joined with existing database objects and transformed in a complex manner or the external data volume is large and used only once.SQL*Loader, on the other hand, might still be the better choice for loading of data where additional indexing of the staging table is necessary. This is true for operations where the data is used in independent complex transformations or the data is only partially used in further processing.

Page 95: 9ib_SQL

SQL and PL/SQL Enhancements 2-52

Example of Defining External TablesCREATE table employees_ext (employee_id NUMBER, first_name Char(30)), last_name CHAR(30), …)ORGANIZATION EXTERNAL ( -- External TableTYPE oracle_loader –- Access DriverDEFAULT DIRECTORY delta_dir –- Files DirectoryACCESS PARAMETERS –- Similar to SQL*Loader

(RECORDS DELIMITED BY NEWLINEFIELDS TERMINATED BY ',‘BADFILE 'bad_emp_ext' LOGFILE 'log_emp_ext' MISSING FIELDS ARE NULL)LOCATION ('emp1.txt','emp2.txt')

PARALLEL 5 –- Independent from the number of filesREJECT LIMIT UNLIMITED;

Example of Defining External TablesAn External Table can be created with single CREATE TABLE DDL command. This will create the meta information which is necessary to access the external data seamlessly from inside the database.The following information must be provided:•Columns and data types for access in the database•Where to find the external data •Access driver: It is the responsibility of the access driver and the external table layer to do the necessary transformations required on the data in the data file so that it matches the external table definition. There is one access driver for every implementation of an external table type.•Format of the external data, similar to SQL*Loader •Degree of parallelism: Note, that the degree is not dependent on the number of external data filesIn the example above an external table named employees_ext is defined. Delta_dir is a directory where the external flat files are residing. This example also use the default access driver for this implementation of external tables. It is called oracle_loader.The access parameters control the extraction of data from the flat file using record and file formatting information. The directory object was introduced in Oracle8i. A directory object must be created within the database using the CREATE DIRECTORY command pointing to the actual location of the flat files. Read access must be given on the directory object, to the users accessing the external table.

Page 96: 9ib_SQL

SQL and PL/SQL Enhancements 2-53

Querying External Tables

SELECT *

FROM employees_ext ;

SELECT *

FROM employees_ext ;

OS file

Querying External TablesIn the above example when the external table employees_ext is queried the data is retrieved from the external data files. When the user selects data from the external table, the dataflow goes from the external data source to the Oracle SQL engine where data is processed. As data is extracted, it is transparently converted by the external agent(s) from its external representation into an equivalent Oracle native representation (the loader stream).

Page 97: 9ib_SQL

SQL and PL/SQL Enhancements 2-54

Data Dictionary Information for External Tables

• DBA_EXTERNAL_TABLES

- OWNER- NAME- TYPE_OWNER- TYPE_NAME- DEFAULT_DIRECTORY

_OWNER- DEFAULT_DIRECTORY

_NAME- REJECT_LIMIT

• DBA_EXTERNAL_LOCATIONS– OWNER– TABLE_NAME– LOCATION– DIRECTORY_OWNER– DIRECTORY_NAME

Data Dictionary Information for External TablesDBA_EXTERNAL_TABLES lists the specific attributes of all the external tables in the system:

OWNER : Owner of the external tableNAME : Name of the external tableTYPE_OWNER : Implementation type ownerTYPE_NAME : Implementation type nameDEFAULT_DIRECTORY_OWNER : Owner of the default directory for this external tableDEFAULT_DIRECTORY_NAME : Name of the default directory for this external tableREJECT_LIMIT : Reject limit

DBA_EXTERNAL_LOCATIONS lists the specific flat files and corresponding Oracle DirectoriesOWNER : Owner of the external tableTABLE_NAME : Name of the external tableLOCATION : Flat File nameDIRECTORY_OWNER : Owner of the directory for this external tableDIRECTORY_NAME : Name of the directory for this external table

Page 98: 9ib_SQL

SQL and PL/SQL Enhancements 2-55

Benefits of External Tables

• Can be used for loading data into the database• Allow data to be stored outside the database

Page 99: 9ib_SQL

SQL and PL/SQL Enhancements 2-56

Other Data Warehousing Features

• Grouping sets allow the user to specify groups of interest in the GROUP BY clause

• WITH clause allows the reuse of the same query block, when it occurs more than once within a complex query, through materialization

REFERENCENote: Grouping Sets and the WITH clause are covered in greater detail in the Business Intelligence module

Page 100: 9ib_SQL

SQL and PL/SQL Enhancements 2-57

Overview of FOR UPDATE WAITIn prior releases the 'SELECT … FOR UPDATE' statement has only two alternatives when the rows being selected are already locked: wait for the lock to be released or return immediately with an error message. Another alternative has been added in Oracle9i to allow the user to specify the time interval to wait before returning with the error.

Overview of FOR UPDATE WAIT

• The SELECT FOR UPDATE statement has been modified to allow the user to specify how long the command should WAIT if the rows being selected are locked.

• If NOWAIT is specified then the default behavior is still followed

Page 101: 9ib_SQL

SQL and PL/SQL Enhancements 2-58

Example of Using FOR UPDATE WAIT

SELECT * FROM EMPLOYEESWHERE DEPARTMENT_ID = 10

FOR UPDATE WAIT 20;

Example of Using FOR UPDATE WAITAn integer can be specified after the key word WAIT to indicate the number of seconds to wait for a lock to be released. In the above example the query waits 20 seconds to obtain a lock and if it is unable to obtain the lock in that time interval it returns an error.

Page 102: 9ib_SQL

SQL and PL/SQL Enhancements 2-59

Benefits of FOR UPDATE WAIT

• Prevents the indefinite waits on locked rows• Allows more control on the wait time for locks

in applications• Very useful for Windows based applications

because these applications cannot wait for extended time intervals

Page 103: 9ib_SQL

SQL and PL/SQL Enhancements 2-60

Summary

In this lesson, you should have learned about:• Constraint and Index Enhancements• Globalization enhancement• Data warehousing features• Other enhancements

Page 104: 9ib_SQL

SQL and PL/SQL Enhancements 3-1

Enhancements to PL/SQL

Page 105: 9ib_SQL

SQL and PL/SQL Enhancements 3-2

Objectives

After this lesson , you should be able to describe the following PL/SQL enhancements in Oracle9i:

• SQL related enhancements– CASE statements– Cursor subqueries– Common SQL parser

Page 106: 9ib_SQL

SQL and PL/SQL Enhancements 3-3

Objectives

• Performance – Native compilation – Bulk binds in native dynamic SQL– Table functions– Transparent performance improvements

• Internet – UTL_HTTP enhancements

Page 107: 9ib_SQL

SQL and PL/SQL Enhancements 3-4

SQL Related Enhancements

• CASE statements

• Cursor subqueries• Common SQL parser

Page 108: 9ib_SQL

SQL and PL/SQL Enhancements 3-5

PL/SQL CASE Statement

• Supports the grammar rules of SQL 99• Allows labels • Has the following types

– CASE expression– PL/SQL simple CASE expression– PL/SQL searched CASE expression

– CASE statement– PL/SQL simple CASE statement– PL/SQL searched CASE statement

PL/SQL CASE StatementPL/SQL CASE statement supports the grammar rules of SQL CASE statement as specified in SQL: 1999. There is a slight syntax extension to allow PL/SQL CASE statements to be labeled. The label can be optionally used in the final END clause. This is to ensure that they are seamless with other CASEstatements.

Page 109: 9ib_SQL

SQL and PL/SQL Enhancements 3-6

Types of CASE

• CASE expression can be used:

– similar to any SQL expression – as an assignment to variables , within a

SQL statement or in a logical operation– Starts with CASE and terminates with END

• CASE statement can be used:

– As an independent statement similar to the IF…THEN…ELSE logical statement

– Starts with CASE and terminates with an END CASE

Page 110: 9ib_SQL

SQL and PL/SQL Enhancements 3-7

Simple vs. Searched CASE

• Simple CASE :

– Can conditionally evaluate a single variable/expression for multiple values

– Cannot contain comparison operators in the WHEN clause

• Searched CASE statement :

– Is more flexible– Each WHEN clause

– can have different variables if needed– can have comparison operators

Page 111: 9ib_SQL

SQL and PL/SQL Enhancements 3-8

Simple CASE ExpressionIn the above example the CASE expression is being assigned to a variable. In this type of usage, each executable statement following the WHEN clause does not require a semicolon. Also the CASEexpression is terminated with just an END statement not an END CASE.The above example was written in prior releases as follows:

FUNCTION get_comm (p_comm NUMBER) RETURN VARCHAR2 isv_comm VARCHAR2(10);

BEGINIF p_comm = .15 THEN

v_comm := 'fifteen percent';ELSIF p_comm = .2 THEN

v_comm := 'twenty percent';ELSE

v_comm :='thirty percentEND IF;RETURN v_comm;

END;

CREATE OR REPLACE FUNCTION get_comm (p_comm NUMBER)RETURN VARCHAR2 isv_comm VARCHAR2(10);

BEGINv_comm :=

CASE p_commWHEN .15 THEN 'fifteen percent'WHEN .2 THEN 'twenty percent'ELSE 'thirty percent'

END;RETURN v_comm;

END;

Example of Simple CASE Expression

Page 112: 9ib_SQL

SQL and PL/SQL Enhancements 3-9

Example of Simple CASE StatementThe above example shows a CASE statement. In this instance the CASE statements ends with an END CASE statement and every executable statement following the WHEN clause must be terminated with a ";". In prior releases the above example was coded as:

FUNCTION get_comm (p_comm NUMBER) RETURN VARCHAR2 isv_comm VARCHAR2(10);

BEGINIF p_comm = .15 THEN

v_comm := 'fifteen percent';ELSIF p_comm = .2 THEN v_comm := 'twenty percent';

ELSE v_comm :='thirty percent

END IF;RETURN v_comm;

END;

CREATE OR REPLACE FUNCTION get_comm (p_comm NUMBER)RETURN VARCHAR2 is

v_comm VARCHAR2(10);BEGIN

CASE p_commWHEN .15 THEN

v_comm := 'fifteen percent';WHEN .2 THEN

v_comm := 'twenty percent';ELSE

v_comm := 'thirty percent';END CASE;RETURN v_comm;

END;

Example of Simple CASE Statement

Page 113: 9ib_SQL

SQL and PL/SQL Enhancements 3-10

Searched CASE ExpressionIn a searched CASE expression each WHEN clause can have a different conditional expression. The conditions can take the form of "variable_expression operator value_expression". The operator can be any comparison operator that can be used in PL/SQL. In the above example the function GET_SAL_GRADE accepts the salary and returns the salary grade based on the CASE expression.

CREATE OR REPLACE FUNCTION get_sal_grade (p_sal NUMBER)RETURN VARCHAR2 isv_grade VARCHAR2(25);

BEGINv_grade :=

CASEWHEN p_sal < 10000 THEN

'salary is low'WHEN p_sal between 10000 and 50000 THEN

'salary is average'ELSE

'salary is high'END;

RETURN v_grade;END;

Example of Searched CASE Expression

Page 114: 9ib_SQL

SQL and PL/SQL Enhancements 3-11

Example of Searched CASE Statement In the above example the function GET_RAISE computes the raise based on the CASE statement using salary values.

CREATE OR REPLACE FUNCTION get_raise (p_sal NUMBER) RETURN VARCHAR2 is

v_raise VARCHAR2(10); BEGIN

CASEWHEN p_sal < 10000 THEN

v_raise :='raise is 10%';WHEN p_sal > = 10000 THENv_raise := 'raise is 15%';

END CASE;RETURN v_raise;

END;

Example of Searched CASE Statement

Page 115: 9ib_SQL

SQL and PL/SQL Enhancements 3-12

NULLIF and COALESCE expressionNULLIF ExpressionThe semantics of PL/SQL NULLIF expression are defined by rewriting it as

CASEWHEN expression1 = expression2 THEN NULLELSE expression1

END CASE;COALESCE ExpressionWhen a PL/SQL COALESCE expression has exactly two arguments, the semantics are defined by rewriting it as

CASEWHEN expression1 IS NOT NULL THEN expression 1ELSE expression 2

END CASE;When COALESCE has three or more arguments, it has the form COALESCE ( expression 1, expression 2, expression 3, . . ., expression n) the semantics are defined by rewriting it as

CASEWHEN expression1 IS NOT NULL THEN expression 1ELSE COALESECE (expression2, expression3, . . ., expression n)

END CASE;

PL/SQL NULLIF and COALESCE

• PL/SQL NULLIF and COALESCE are forms of shorthand for PL/SQL CASE expressions.

• The NULLIF is reverse of the NVL function• The COALESECE is similar to the DECODE

function

Page 116: 9ib_SQL

SQL and PL/SQL Enhancements 3-13

PL/SQL NULLIF expressionThe above example can be rewritten as :PROCEDURE get_comm_pct (p_comm NUMBER) is

v_result NUMBER;BEGIN

v_result :=CASE p_comm

WHEN 0 THEN NULLELSE p_comm

END ;DBMS_OUTPUT.PUT_LINE (' v_result is ' || v_result *100 ||'%');

END;v_result is 20%PL/SQL procedure successfully completed.

CREATE OR REPLACE PROCEDURE get_comm_pct (p_comm NUMBER) is

v_result VARCHAR2(10);BEGIN

v_result := NULLIF(p_comm, 0 );

DBMS_OUTPUT.PUT_LINE ('The commission percent is '|| v_result*100||'%');

END;

The commission percent is 20%PL/SQL procedure successfully completed.

Example of PL/SQL NULLIF

Page 117: 9ib_SQL

SQL and PL/SQL Enhancements 3-14

PL/SQL COALESCE expression

The above example can be rewritten as :PROCEDURE get_comm_pct (p_comm NUMBER) is

v_result number;BEGIN

CASE WHEN p_comm IS NOT NULL THEN v_result := p_comm;ELSE v_result := 0;

END CASE ;DBMS_OUTPUT.PUT_LINE (' v_result is ' || v_result *100 ||'%');

END;v_result is 20%PL/SQL procedure successfully completed.

CREATE OR REPLACE PROCEDURE get_comm_pct (p_comm NUMBER) is

v_result number;BEGIN

v_result := COALESCE( p_comm, 0);DBMS_OUTPUT.PUT_LINE

('The commission percent is '||v_result*100||'%');

END;

The commission percent is 20%PL/SQL procedure successfully completed.

Example of PL/SQL COALESCE

Page 118: 9ib_SQL

SQL and PL/SQL Enhancements 3-15

Overview of Cursor Subquery

• The cursor subquery opens a nested cursor for each evaluation of the cursor expression.

• For each row of parent query, it returns a cursor in the SELECT list corresponding to the cursor expression.

• Fetches have to be performed to retrieve the results of a subquery

Page 119: 9ib_SQL

SQL and PL/SQL Enhancements 3-16

Usage of Cursor Subqueries

• In PL/SQL, cursor subquery is allowed in the following contexts:– Ref Cursor– Explicit Cursor

• Cursor subqueries are not allowed in– Implicit cursors

Notes: Cursor subqueries were introduced in SQL in Oracle8.1.7 as cursor expressions. Please refer Oracle 8.1.7 SQL reference manual for more information on this feature

Page 120: 9ib_SQL

SQL and PL/SQL Enhancements 3-17

Example of Cursor Subquery in Ref CursorIf a ref cursor is bound to a cursor subquery as shown in above example then subsequent fetch from this ref cursor is another ref cursor.In the above example employees and department are existing tables. The ref cursors, with which the results of the cursor subquery are fetched should be weak ref cursors. Strong ref cursors are not supported. If the subquery references outer query through correlation variables then it is impossible to map the sub query to store a ref cursor. Note: This feature was included for SQL as cursor expressions in Oracle 8.1.7

DECLARETYPE refcursortype IS REF CURSOR;n NUMBER; emprow employees%rowtypeempcur1 refcursortype;empcur2 refcursortype;

BEGINOPEN empcur1 FORSELECT cursor(SELECT * FROM employees)

FROM departments;FETCH empcur1 INTO empcur2;FETCH empcur2 INTO emprow;

END;

Example of Cursor Subquery in Ref Cursor

Page 121: 9ib_SQL

SQL and PL/SQL Enhancements 3-18

Example of Cursor Subquery in Explicit CursorIf an explicit cursor is bound to a cursor subquery, as shown above then a subsequent fetch returns another ref cursor that can be used to fetch the results from the result of the subquery

DECLARETYPE refcursortype IS REF CURSOR;emprow employees%rowtypeempcur1 refcursortype;CURSOR c1 is SELECT CURSOR (SELECT * FROM employees)from department;

BEGINOPEN c1LOOP

FETCH c1 INTO empcur1;…

END LOOP;END;

Example of Cursor Subquery in Explicit Cursor

Page 122: 9ib_SQL

SQL and PL/SQL Enhancements 3-19

Cursor Subquery- Nested Cursors Attributes

Nested cursor • Is prepared the first time an operation is

performed on it• Resources are released after all the nested

cursors associated with this cursor have been prepared

• The parent is checked at each preparation to verify if this is the last nested cursor so that resources may be released

Page 123: 9ib_SQL

SQL and PL/SQL Enhancements 3-20

Introducing the Common SQL Parser

The Common SQL Parser• Reduces duplication of SQL analysis• Allows PL/SQL to pick up new SQL features as

they are implemented in the RDBMS

Introducing the Common SQL ParserThe common SQL parser replaces PL/SQL's compile-time analysis of a static SQL statement with analysis using a SQL component shared with the RDBMS. This reduces duplication of SQL analysis , allowing PL/SQL to pick up new SQL features as they are implemented in the RDBMS and eliminating bugs due to differences in SQL analysis between SQL and PL/SQLA new compile-time switch disables the common SQL parser and reverts into PL/SQL analysis for SQL statements. The syntax of this switch is:ALTER [PACKAGE/FUNCTION/PROCEDURE/TRIGGER/TYPE] SET SQL_PARSER =(LATEST | 81_COMPATIBLE);The default is LATEST. 81_COMPATIBLE disables the common parser and reverts to PL/SQLprocessing.Using this switch has two implications:1. No new SQL syntax introduced in Oracle9i will be available in static SQL statements in aprogram unit. Some SQL features introduced in Oracle 8.1.6 (e.g., window functions) will also notbe available. The suggested workaround is to use dynamic SQL, where these features areavailable.2. Static SQL processing will use the current infrastructure, so programs valid in Oracle 8.1 willcontinue to compile without errors in static SQL.

Page 124: 9ib_SQL

SQL and PL/SQL Enhancements 3-21

Visible Effects of Common SQL parser

• Wrap files expose the text of static SQL statements

• Changes PLS-error messages to ORA-error messages

Support for Common SQL parserPL/SQL wrap filesPrior to Oracle9i wrap files (files generated by the wrap utility) exposed column and variable names and string literals occurring in PL/SQL program units, but not entire static SQL statements. In Oracle9i wrap files expose the text of static SQL statementsError MessagesA number of error messages raised during the analysis of static SQL statements change from PLS_errors to ORA-errors. The common SQL parser raises errors during SQL compilation that PL/SQL analysis did not catch. This allows earlier detection of static SQL errors.Compatibility & MigrationDuring an upgrade to Oracle9i from a previous version of Oracle, PL/SQL program units thatcompiled correctly in the previous version may compile with errors in static SQL statements inOracle9i. These errors are a result of the stricter compile-type checking enabled by the common SQLparser. It is recommended that the user update the PL/SQL code to eliminate any new errors. If theusers do not have access to the source code, they can disable the common SQL parser for theprogram unit containing errors using the compile-time switch.

Page 125: 9ib_SQL

SQL and PL/SQL Enhancements 3-22

Other PL/SQL Language Enhancements

• Support for new datetime datatypes including:– Timestamp– Timestamp with time zone– Interval day to second – Interval year to month …

• Support for SQL Unicode enhancements• Seamless support of BLOB and CLOB datatypes• Support for object type evolution and single inheritance• Support for multi level collections

Other PL/SQL Language EnhancementsOracle9i SQL and PL/SQL include support for the SQL: 1999 timestamp and interval datatypes. In addition Oracle supports timestamp with local time zone and daylight savings time. Various operators and functions have been added to support these new datatypes.Oracle9i SQL and PL/SQL provide support for implicit Unicode conversion.REFERENCE:Note: For more information on these features please refer to the Lesson SQL Enhancements in this moduleSeamless support for LOBs in the language. String built-ins (such as SUBSTR etc.) now work on lob arguments also. CHAR and VARCHAR variables can be assigned back and forth to LOB variables.REFERENCENote: For more information on these features please refer to the Lesson LOB enhancements in this moduleOracle9i includes support for creation of subtypes of object types and creation of type hierarchies based on a single inheritance model. Subtypes can be used in PL/SQL wherever object types can appear. PL/SQL also supports substitutability and dynamic dispatch.Oracle9i includes support for type evolution that is object types can be evolved by adding, modifying attributes and methods. Persistent data evolves to match the updated type structure.REFERENCENote: For more information on these features please refer to the Objects module under Development Platform

Page 126: 9ib_SQL

SQL and PL/SQL Enhancements 3-23

Performance Enhancements in PL/SQL Oracle9i

• Native compilation• PL/SQL table functions• Bulk bind enhancements• Bulk dynamic SQL• Transparent performance enhancements

Page 127: 9ib_SQL

SQL and PL/SQL Enhancements 3-24

Overview of Native Compilation of PL/SQLA PL/SQL library unit is compiled into bytecode or MCODE (machine dependent code) and theMCODE is loaded into the library cache part of the shared pool in the System Global Area(SGA). When multiple users connected to an Oracle instance execute the same PL/SQLprogram, they share a single copy of the compiled PL/SQL program. Each user session gets itsown private area to store values specific to the session such as the values of package variables(the package instantiation). The location of this session specific private area will be in theProcess Global Area (PGA) of the user if the session is established via a dedicated server. It willbe in the SGA in the case of a Multi Threaded Server.When a PL/SQL library unit is compiled native, it is stored as a shared library in the file system.When a user session references a natively compiled PL/SQL library unit, the correspondingshared library is mapped to the virtual address space of the oracle process. That means thecompiled program is located in the PGA. When multiple users reference the same nativelycompiled PL/SQL library unit, the shared library is mapped to the virtual address space of eachOracle process. But by virtue of being a shared library, there is a single copy of the sharedlibrary in the physical memory. The instantiation of natively compiled PL/SQL packages ishandled exactly the same manner as the packages compiled to MCODE.

Overview of Native Compilation of PL/SQL

• In Oracle9i a PL/SQL library unit is compiled as native code

• It is then stored as a shared library in the file system.

• A user session referencing a natively compiled PL/SQL library unit, the corresponding

• The compiled program is located in the PGA.• The instantiation of natively compiled PL/SQL

packages is handled exactly the same manner as the packages compiled to MCODE.

Page 128: 9ib_SQL

SQL and PL/SQL Enhancements 3-25

New parameters for Native Compilation ContinuedPLSQL_COMPILER_FLAGS is a parameter used by the PL/SQL compiler. It specifies a list of compiler flags as a comma separated list of strings. The parameter can be set at a system wide level using the ALTER SYSTEM command. The ALTER SESSION command can be used to change the value of this parameter for a specific session. If "INTERPRETED" is specified as one of the flags, then PL/SQL modules will be compiled to PL/SQL byte-code format. Such modules executed by the PL/SQL interpreter engine. This is the default PL/SQL compilation mode in releases prior to Oracle9i o If "NATIVE" is specified as one of the flags, then PL/SQL modules (with the possible exceptions of top-level anonymous PL/SQL blocks) will be compiled to native (machine) code. Such modules will be executed natively without incurring any interpreter overhead. o If "DEBUG" is specified as one of the flags, then PL/SQL modules will be compiled with PROBE debug symbols.PLSQL_COMPILER_NATIVE_LIBRARY_DIR is a parameter used by the PL/SQL compiler. It specifies the name of a directory where the shared objects produced by the native compiler are stored. The reason to have a parameter to specify such a directory is so that the DBA can choose the location of the shared objects produced by the native compiler for each module as the need arises. This parameter can only be modified by the DBA via an ALTER SYSTEM command or specifying a value in the init.ora file before the instance is started.

New Parameters for Native Compilation

• PLSQL_COMPILER_FLAGS• PLSQL_COMPILER_NATIVE_LIBRARY_DIR• PLSQL_NATIVE_MAKE_UTILITY• PLSQL_NATIVE_C_COMPILER• PLSQL_NATIVE_LINKER

Page 129: 9ib_SQL

SQL and PL/SQL Enhancements 3-26

New parameters for Native Compilation ContinuedPLSQL_NATIVE_MAKE_UTILITYThis parameter specifies the full path name of a make utility such as make in UNIX or gmake(GNU make). The make utility is needed to generate the shared object or DLL from thegenerated C source. This parameter can only be modified by the DBA via an ALTER SYSTEM command or specifying a value in the init.ora file before the instance is started.PLSQL_NATIVE_MAKE_UTILITYThis parameter specifies the full path name of a make file. The make utility (specified by thePLSQL_NATIVE_MAKE_UTILITY) uses this make file to generate the shared object or DLL. A port specific make file is shipped for each platform which contains the rules for the make utility to generate DLLs on that platform. This parameter can only be modified by the DBA via an ALTER SYSTEMcommand or specifying a value in the init.ora file before the instance is started.PLSQL_NATIVE_C_COMPILERThis parameter specifies the full path name of a C compiler which is used to compile thegenerated C file into an object file. This parameter is optional. The platform specific make filethat is shipped for each platform will contain a default value for this parameter. If a value isspecified for this parameter, it will override the default value in the make file. This parametercan only be modified by the DBA via an ALTER SYSTEM command or specifying a value in the init.ora file before the instance is started.PLSQL_NATIVE_LINKERThis parameter specifies the full path name of a linker such as ld in UNIX or GNU ld which is used to link the object file into a shared object or DLL. This parameter is optional. The platform specific make file that is shipped for each platform will contain a default value for this parameter. If a value is specified for this parameter, it will override the default value in the.make file. This parameter can only be modified by the DBA via an ALTER SYSTEM command or specifying a value in the init.ora file before the instance is started.

New Parameters for Native Compilation

• PLSQL_COMPILER_FLAGS• PLSQL_COMPILER_NATIVE_LIBRARY_DIR• PLSQL_NATIVE_MAKE_UTILITY• PLSQL_NATIVE_C_COMPILER• PLSQL_NATIVE_LINKER

Page 130: 9ib_SQL

SQL and PL/SQL Enhancements 3-27

Steps for Enabling Native Compilation1. ALTER SYSTEM SET PLSQL_NATIVE_LIBRARY_DIR =

'/orahome/dbs/native_plsql';

2. ALTER SYSTEM SET PLSQL_NATIVE_MAKE_UTILITY = '/usr/local/bin/make';ALTER SYSTEM SET PLSQL_NATIVE_MAKE_FILE_NAME =

'/orahome/admin/spnc_makefile.mk';

--turn the feature on3. ALTER SESSION SET

plsql_compiler_flags = 'NATIVE';

--recompile programs4. ALTER FUNCTION emp_upd COMPILE;

--turn off the feature5. ALTER SESSION SET

plsql_compiler_flags = 'INTERPRETED';

Enabling Native Compilation1. The first parameter is required: ALTER SYSTEM SET PLSQL_NATIVE_LIBRARY_DIR=

'/orahome/dbs/native_plsql'; 2. One of the following two pairs of parameters must also be set: ALTER SYSTEM SET PLSQL_NATIVE_MAKE_UTILITY=

'/usr/local/bin/make'; ALTER SYSTEM SET PLSQL_NATIVE_MAKE_FILE_NAME=

'/orahome/admin/spnc_makefile.mk'; or ALTER SYSTEM SET PLSQL_NATIVE_C_COMPILER= '/USR/LOCAL/BIN/CC'; ALTER SYSTEM SET PLSQL_NATIVE_LINKER= '/USR/CCS/BIN/LD';

3. To turn the feature on: ALTER SESSION SET PLSQL_COMPILER_FLAGS='NATIVE';

4. To turn the feature off: ALTER SESSION SET PLSQL_COMPILER_FLAGS='INTERPRETED';

Subsequent compiles in the same session after one of these alter sessions is executed picks up the last value of "PLSQL_COMPILER_FLAGS". Implicit recompiles of the same program are done with whatever setting was in effect when it was last compiled. CONFIDENTIALNote:This feature's API may change prior to our releasing the feature. These are the current parameter descriptions. Due to some late feedback regarding security, some of these may be modified or removed

Page 131: 9ib_SQL

SQL and PL/SQL Enhancements 3-28

Benefits of Native Compilation of PL/SQL

• Faster execution of PL/SQL programs by generating native "C" code instead of byte code

• Improvement in execution speed due to the following factors:– Eliminating the overhead associated with

interpreting byte code– Control flow is much faster in native code than

in interpreted code– Compiled code corresponding to a PL/SQL

program is mapped to a PGA as opposed to SGA

– PL/SQL that does not contain SQL references is 2-10 times faster.

Overview of NExP: Native Execution of PL/SQLA PL/SQL program is compiled to native code in two phases: the program is translated to C code which is subsequently compiled to native code. For PL/SQL fixed packages, the compiled code is statically linked to the Oracle executable whereas for end-user PL/SQL programs, the compiled code is dynamically linked to an Oracle process. A C compiler is required for the feature to be implementedNative compilation provides an improvement in execution speed due to the following factors:The overhead associated with interpreting the byte-code is eliminatedControl flow is much faster in native code than in interpreted code This is because jumps are label based on C code. Function calls to targets in the same compilation unit are mapped to C function calls. The cost of setting up a frame is also cheaper because the primary memory for the frame is allocated on the C stack as opposed to the PGA in the case of MCODE. Exception handling is also much faster in native code because exceptions are implemented as jumps to switch statements containing the exception handler code. There is no run-time overhead associated with looking up an exception handler table as in the case of MCODE based exception handlingThe compiled code corresponding to a PL/SQL program is mapped into the PGA as opposed to the SGA into which the MCODE is loaded. This should result in lesser contention for SGA and thus better scalability. Also in the case of large PL/SQL programs, the startup time should be faster on demand paged systems. The MCODE is loaded in its entirety into SGA.The constant pool is also mapped into the PGA as constant data. The constant pool items such as string literals, etc. can be arbitrarily long as the PGA is paged by the operating system. Similarly, the handle segment need not be paged in the case of native compilation. PL/SQL execution is 2-10 times faster however it does not speed up SQL execution.

Page 132: 9ib_SQL

SQL and PL/SQL Enhancements 3-29

Restrictions to Native Compilation of PL/SQLGranularity of Native CompilationThe granularity of native compilations is a library unit or compilation unit i.e. a package spec, apackage body, a top-level procedure or function. Individual functions or procedures in apackage can not be compiled native.Package/Type specification and body must be compiled in the same modeIf the specification of a PL/SQL package is compiled for native (interpreted) execution, then thebody must also be compiled for native (interpreted) execution. This restriction enables fasterprocedure calls between natively compiled libunits. [Note: This is perhaps a restriction we canrelax, if required, if it turns out not to give us a significant performance advantage.]Anonymous BlocksAnonymous blocks will always be compiled for interpreted execution. [We do not want to leavedisk footprints, namely DLLs, for anonymous blocks. This creates additional complications interms of "naming" the anonymous DLLs, and in terms of cleanup of these DLLs in case of aserver crash, etc.]

Restrictions to Native Compilation of PL/SQL

• Package/Type specification and body must be compiled in the same mode

• Individual functions or procedures in a package can not be compiled native

• Anonymous blocks will always be compiled for interpreted execution

Page 133: 9ib_SQL

SQL and PL/SQL Enhancements 3-30

Overview of Oracle9i Bulk Bind Enhancements

• Bulk bind features have been enhanced in Oracle9i to support more efficient and convenient bulk bind operations

• Restrictions on usage of collections in SELECTand FETCH clauses has been removed

• Error handling for failure in bulk binds has been provided

Overview of Oracle9i Bulk Bind EnhancementsBulk bind features of PL/SQL in Oracle9i have been enhanced to support more convenient and efficient bulk bind operations and provide an error handling mechanism. One of the restrictions about bulk binds in prior releases of Oracle is that variables defined in SELECT and FETCH clauses cannot be collections of records. In Oracle9i the bulk binding feature has been enhanced to allow users to easily retrieve multiple rows from database tables. Bulk binding of records used in INSERT and UPDATE statements is also now supported.In addition previously bulk bind operations, such as FORALL INSERT/UPDATE/DELETE , stopped immediately whenever there was an error during its execution and an exception would then be raised. In certain applications it is better to handle the exception and continue processing. In Oracle9i An error handling mechanism has been incorporated such that errors during a bulk bind operation are collected and returned together when the operation completes.

Page 134: 9ib_SQL

SQL and PL/SQL Enhancements 3-31

Bulk Bind Operations

Classification of bulk bind operations:• Define • In-bind • Out-bind

Bulk Bind OperationsBinding operations in PL/SQL can be classified into three categories: define, in-bind and out-bind. Define refers to returning values from database tables into PL/SQL variables or host variables when database tables are retrieved using SELECT or FETCH statements. In-bind refers to sending values in the VALUES clauses in INSERT statements or the SET clauses in UPDATE statements to database tables. Out-bind refers to returning values from the affected rows by DELETE, INSERT or UPDATE statements into PL/SQL variables or host variables.

Page 135: 9ib_SQL

SQL and PL/SQL Enhancements 3-32

FORALL Statement Enhancements

The keywords SAVE EXCEPTIONS , in the FORALL DELETE/UPDATE/INSERT statements , are required if the users want the bulk bind operation to complete regardless of the occurrences of errors. All of the errors occurring during the execution are saved in the new cursor attribute, %BULK_EXCEPTIONS. %BULK_EXCEPTIONS is a bulk attribute of a collection of records which have two integer attributes. The first attribute, index is used to store the corresponding SQL error code, SQLCODE. The user can get the corresponding SQL error message by calling SQLERRM with the SQL error code as the parameter. The number of errors is saved in the count attribute of %BULK_EXCEPTIONS, that is, %BULK_EXCEPTIONS.COUNT . The subscripts of %BULK_EXCEPTIONS are from 1 to %BULK_EXCEPTIONS.COUNT.Without the keywords, SAVE EXCEPTIONS , in a FORALL statement , DELETE/UPDATE/INSERTstatement inside the FORALL stops whenever an error occurs. In this situation , SQL%BULK_EXCEPTIONS.COUNT is one and SQL%BULK_EXCEPTIONS contains one record.If there is no error at all during the execution of a FORALL statement, %BULK_EXCEPTIONS.COUNTreturns zero.The values of this new cursor attribute always refer to the most recently executed FORALL statement. %BULK_EXCEPTIONS cannot be assigned to other collections. It also cannot be passed as a parameter to subprograms.

FORALL index IN lowerbound .. upperbound[SAVE EXCEPTIONS]DELETE/UPDATE/INSERT statement

FORALL Statement Enhancements

Page 136: 9ib_SQL

SQL and PL/SQL Enhancements 3-33

Bulk Collect EnhancementsCollection_record_variable in each of the above statements is a variable of a collection of records. The number of fields in the record must be in the same as the number of selected items in the SELECT statement, the number of column names in the INSERT statement, the number of column names in the SET clause in the UPDATE statement, and the number of row expressions in the RETURNING clause respectively.

SELECT <column_list>BULK COLLECT INTO <collection_record_variable> FROM <table_list>;

FETCH {cursor_name|cursor_variable_name|:host_cursor_variable_name} BULK COLLECT INTO<collection_record_variable>;

BULK COLLECT Enhancements

Page 137: 9ib_SQL

SQL and PL/SQL Enhancements 3-34

Error Handling for Bulk Binds

• In prior releases, exceptions occurring during the FORALL, stopped the program execution immediately and raised an exception

• The new error handling mechanism saves the error information and continues execution

• All the errors occurring during the execution are returned together after the program completes.

Page 138: 9ib_SQL

SQL and PL/SQL Enhancements 3-35

DECLARETYPE numtab IS table of number;v_discount numtab:=

numtab(10,0,15,20,25,0,60,80,34,0);total_error NUMBER;

BEGINFORALL i IN v_discount.first .. v_discount.last

SAVE EXCEPTIONS UPDATE productsset min_price =

list_price - list_price/v_numtab(i);Total_error := SQL%BULK_EXCEPTIONS.COUNT;

Example of Exception Handling

Page 139: 9ib_SQL

SQL and PL/SQL Enhancements 3-36

Example of Exception Handling (continued)In the example above, errors, whose SQL error codes are 1476 (zero_divide), had occurred when I =2, 6,10. The bulk bind operation would finish the whole operation and then return all of the errors together into the new cursor attribute, %BULK_EXCEPTIONS.SQL%BULK_EXCEPTIONS.COUNT is 3 and the contents of SQL%BULK_EXCEPTIONS are (2,1476),(6,1476),(10,1476).The output of the above program is the following:

Total number of errors is 3Error 1 occurred at iteration 2SQL Error Code is 1476 [Error: ORA-01476:divisor is equal to zero]

Error 2 occurred at iteration 6SQL Error Code is 1476 [Error: ORA-01476:divisor is equal to zero]

Error 3 occurred at iteration 10SQL Error Code is 1476 [Error: ORA-01476:divisor is equal to zero]

dbms_output.put_line('Total number of errors is ' || total_error);

For i in 1 .. Total_error LOOPdbms_output.put_line('Error '||i||'occurred at

iteration' ||SQL%BULK_EXCEPTIONS(i) );

dbms_output.put_line('SQL Error Code is '|| SQL%BULK_EXCEPTIONS(i).error|| '[Error:'|| SQLERRM

(SQL%BULK_EXCEPTIONS(i).error)||']');END LOOP;

END;

Example of Exception Handling (continued)

Page 140: 9ib_SQL

SQL and PL/SQL Enhancements 3-37

Benefits of Bulk Bind Enhancement

• Allow manipulation of an entire collection of rows in a single DML statement

• Reduces the number of database calls.• Allows applications with long transactions to

execute with fewer iterations • Facilitate usage of PL/SQL records and

tables and improve performance

Page 141: 9ib_SQL

SQL and PL/SQL Enhancements 3-38

Overview of Bulk Dynamic SQL

Native dynamic SQL which was introduced in Oracle8i now supports:

• BULK FETCH• BULK EXECUTE IMMEDIATE/BULK EXECUTE • FORALL,COLLECT INTO and RETURNING INTO

Overview of Bulk Dynamic SQLThe following functionality has been introduced for Bulk SQL in embedded dynamic SQL:•BULK FETCH support for cursors opened on dynamic SQL statements•BULK EXECUTE IMMEDIATE and EXECUTE for dynamic SQL•FORALL statement and COLLECT INTO and RETURNING INTO clauses are extended to support dynamic SQL statements

Page 142: 9ib_SQL

SQL and PL/SQL Enhancements 3-39

Example of Bulk Bind for Defining VariablesIn the above example we are using EXECUTE IMMEDIATE to execute a query to retrieve several employee_ids with one call to the database. In earlier releases we had

Note:In the above example num_tab is an object type created as follows:CREATE TYPE num_tab AS TABLE OF NUMBER ;

DECLARETYPE num_tab IS TABLE OF NUMBER;ids num_tab;

BEGINEXECUTE IMMEDIATE 'SELECT employee_id FROM employees'

BULK COLLECT INTO ids;END;

Example of Bulk Bind with Dynamic SQL

Page 143: 9ib_SQL

SQL and PL/SQL Enhancements 3-40

Bulk-bind for Input VariablesInput bind variables of a SQL statement can be bound via FORALL control statement and USING clause. In the above example bulk binding is used to execute an INSERT statement. In the above example we are using EXECUTE IMMEDIATE to execute an INSERT statement passing two collection variables ids and names containing all the department_id and department_name values. Therefore by this method several rows are created using one INSERT statement with one call to the database.

DECLARETYPE num_tab IS TABLE OF NUMBER;TYPE char_tab is TABLE OF VARCHAR2(30);ids num_tab := num_tab (12,13,14,15);names char_tab := char_tab('R/D','IT','GL','PR');

BEGINFORALL iter IN 1..4 EXECUTE IMMEDIATE'INSERT INTO departments(department_id,

department_name)VALUES(:1, :2)'USING ids(iter), names(iter);

END;

Example of Bulk Bind for Input Variables

Page 144: 9ib_SQL

SQL and PL/SQL Enhancements 3-41

Bulk-bind for Output VariablesOnly DML statements have out binds. In bulk bind output bind variables must be bound via RETURNING BULK COLLECT INTO clause. In the above example we are using native dynamic SQL to execute an UPDATE statement passing a variable v_sal for the value to be used for the update. All the updated salaries are then returned using a collection variable saltab.

DECLARETYPE num_tab IS TABLE OF NUMBER;sql_str VARCHAR2(200);v_sal NUMBER := 10000;saltab num_tab;

BEGINsql_str := 'UPDATE employees SET salary = :1

WHERE department_id = 10 RETURNING salary INTO :2';

EXECUTE IMMEDIATE sql_strUSING v_sal RETURNING BULK COLLECT INTO saltab;

END;

Example of Bulk Binding In Output Variables

Page 145: 9ib_SQL

SQL and PL/SQL Enhancements 3-42

Benefits of Bulk Dynamic SQL

• The main benefit of Bulk Dynamic SQL is the improvement in performance.

• Multiple rows can be processed in a single DML statement using bulk SQL

• The number of context switches between SQL statement executor and PL/SQL engine is reduced.

• This allows for faster execution of PL/SQL programs

Page 146: 9ib_SQL

SQL and PL/SQL Enhancements 3-434

Overview of Table Functions

• Oracle 9i supports pipelined and parallelizable table functions– Inputs can be a stream of rows– The output can be pipelined– Evaluation of the table function can be

parallelized • Table Functions can be defined in PL/SQL using a

native PL/SQL interface or in Java or C using the Oracle Data Cartridge Interface (ODCI)

REFERENCENote : For more information on defining the table functions using the ODCI interface please refer Extensibility lesson in the Extensibility module

Page 147: 9ib_SQL

SQL and PL/SQL Enhancements 3-44

PL/SQL Table Functions

New PIPE instruction in PL/SQL• Returns a single result row• Suspend the execution of the function• Function is restarted when the caller requests

the next row

Page 148: 9ib_SQL

SQL and PL/SQL Enhancements 3-45

Example of Table FunctionsExample of Creating Table Functions

In the above example REF_CUR_TYPE and EMP_TAB_TYP are user defined object types. REF_CUR_TYPE is defined as a ref cursor. EMP_TAB_TYPE is an object table. Pipelined functions must have return statements that do not return any values.Here, the idea is to transform each record corresponding to the cursor passed as the parameter for the function and return the corresponding row to the caller. Note that one record is returned as soon as one row is processed.The new PIPELINED instruction in PL/SQL:

• Returns a single result row• Suspend the execution of the function• Function is restarted when the caller requests the next row

PARALLEL_ENABLE is an optimization hint indicating that the function can be executed in parallel. The function should not use session state, such as package variables, as those variables may not be shared among the parallel execution servers.The optional PARTITION argument BY clause is used only with functions that have a REF CURSOR argument type. It lets you define the partitioning of the inputs to the function from the REF CURSOR argument. Partitioning the inputs to the function affects the way the query is parallelized when the function is used as a table function (that is, in the FROM clause of the query). ANY indicates that the data can be partitioned randomly among the parallel execution servers. Alternatively, you can specify RANGE or HASH partitioning on a specified column list.

CREATE OR REPLACE FUNCTION emp_stage_fn(p ref_cur_type) RETURN emp_tab_typPIPELINEDPARALLEL_ENABLE( PARTITION p BY ANY) ISPRAGMA AUTONOMOUS_TRANSACTION;

BEGINFOR rec IN p LOOP…

PIPE ROW (rec);END LOOP;

RETURN;END;

Example of Creating Table Functions

Page 149: 9ib_SQL

SQL and PL/SQL Enhancements 3-46

Using Table FunctionsPipelined functions can be used in the FROM clause of SELECT statements. The result rows are retrieved by Oracle iteratively from the table function implementation. Multiple invocations of a table function , either within the same query or in separate queries result in multiple executions of the underlying implementation, i.e. there is no buffering and reuse of rows. In the above example employees_src represents the source table for the employees table. The data from employees_src is retrieved and formatted for insert, and then inserted into employees using the above statement This can in turn be combined with other data warehousing features such as Multi table inserts.REFERENCENote: For more information on multi table inserts please refer to the lesson on SQL enhancements in this SQL module and also to the Business Intelligence module.

INSERT INTO EMPLOYEESSELECT * FROM

TABLE (emp_stage_fn(cursor(SELECT * FROM employees_src)));

Using Table Functions

Page 150: 9ib_SQL

SQL and PL/SQL Enhancements 3-474

Advantages of PL/SQL Table Functions

• Table functions reduce response time by piping the results as soon as they are produced

• Pipelining eliminates the need for buffering the produced rows

• Table functions can return multiple rows during each invocation.

• The number of invocations are reduced thereby improving performance

Page 151: 9ib_SQL

SQL and PL/SQL Enhancements 3-484

Transparent Performance Enhancements

• Faster record construction and copying– Benchmarks designed to stress the feature

improved up to 5 times. – Less focused benchmarks improved by 5-10%.

• General improvement to "cross-package" references – Considerable improvement in PL/SQL programs

with many dependencies on other PL/SQL programs

– Benchmarks specifically designed to test this feature showed a speedup of over 50%.

– In more generic benchmarks a 5% improvement was seen.

Page 152: 9ib_SQL

SQL and PL/SQL Enhancements 3-494

Transparent Performance Enhancements

• 60% + reduction in overhead of calling PL/SQL procedures from SQL statements.

• For instance the function bonus_fn listed below, executes much faster in Oracle9i

CREATE FUNCTION bonus_fn(p_salary NUMBER) RETURN NUMBER is

BEGIN RETURN p_salary * (.15);

END;

SELECT bonus_fn(salary) from employees;

Page 153: 9ib_SQL

SQL and PL/SQL Enhancements 3-50

Overview of Internet Packages

• All packages are installed by default in SYS schema.

• Granted to all users via public synonyms.• All packages were implemented directly or

indirectly in Java in prior releases. In Oracle9i Java is no longer required

Package

UTL_TCP

UTL_HTTP

UTL_SMTP

UTL_INADDR

Oracle Release

Available in

Oracle8i or in

prior releases

but enhanced

in Oracle9i

Protocol

TCP

HTTP

SMTP

DNS

Page 154: 9ib_SQL

SQL and PL/SQL Enhancements 3-51

Internet Packages Enhancements in Oracle9i

• Extending the interface of UTL_HTTP• Control over HTTP conversations• Support for HTTP cookies

• Overcome current limit on amount of data passed to web servers in the URL

Page 155: 9ib_SQL

SQL and PL/SQL Enhancements 3-52

DECLAREreq UTL_HTTP.req;resp UTL_HTTP.resp;name VARCHAR2(256);value VARCHAR2(1024;

BEGINUTL_HTTP.proxy_host := 'proxy.foo.com';UTL_HTTP.no_proxy_domains(1) :='corp.mycompany.com';req := UTL_HTTP.begin_request

('http://www.hr.corp.mycompany.com');

Example of Using UTL_HTTP to Retrieve Response Headers

Page 156: 9ib_SQL

SQL and PL/SQL Enhancements 3-53

UTL_HTTP.SET_HEADER(req,'User-Agent','Mozilla/4.0');resp := UTL_HTTP.GET_RESPONSE(req);

DBMS_OUTPUT.PUT_LINE('http response status code '||resp.status_code);

DBMS_OUTPUT.PUT_LINE('http response reason phrase '||resp.reason_phrase);

Example of Using UTL_HTTP to Retrieve Response Headers (continued)

Page 157: 9ib_SQL

SQL and PL/SQL Enhancements 3-54

FOR i in 1 .. UTL_HTTP.GET_HEADERS_COUNT(resp) LOOPUTL_HTTP.GET_HEADER

(resp,i,name value);DBMS_OUTPUT.PUT_LINE

(name||':' ||value);END LOOP;

UTL_HTTP.END_RESPONSE(resp);END;

Example of Using UTL_HTTP to Retrieve Response Headers (continued)

Page 158: 9ib_SQL

SQL and PL/SQL Enhancements 3-55

Cookies in UTL_HTTP

• The other new functionality of UTL_HTTP is the use of HTTP cookies in running web applications

• By enabling the HTTP cookies support, a PL/SQL program can instruct the UTL_HTTP package to maintain HTTP cookies set by the web application.

• Cookies are returned to the parent application when the PL/SQL program accesses other web pages.

• There is a transparent connection improvement for processing cookies– Each request does not have to be a session,

instead all requests can be part of the same transaction.

Cookies in UTL_HTTPIn normal circumstances, PL/SQL programs do not need to examine or change the cookie information stored in the UTL_HTTP package. The cookies are maintained by the package transparently for the programs. Note that the cookies are maintained inside the UTL_HTTP package and they last for the duration of the database session only. For those PL/SQL applications that require cookies to be maintained beyond the life-time of a database session, they can read the cookies using GET_COOKIES, store them persistently in a database table, and restore the cookies back in the package using SET_COOKIES in the next database session. Allthe fields in the cookie record, except for the comment field, must be stored. Care must be taken not to alter the cookie information, or it may result in an application error in the Web server or may compromise the security of the PL/SQL and the web server applications.

Page 159: 9ib_SQL

SQL and PL/SQL Enhancements 3-56

Cookies in UTL_HTTP• New variables

– cookie is the PL/SQL record type that represents a HTTP cookie.

– cookie_table is a PL/SQL index-by table type that represent a collection of HTTP cookies.

• New Functions– get_cookie_support– set_cookie_support– get_cookie_count– get_cookies– set_cookies– clear_cookies

An example that shows how to retrieve and restore cookiesCREATE TABLE my_cookies (session_id BINARY_INTEGER,name VARCHAR2(256),value VARCHAR2(1024),domain VARCHAR2(256),expire DATE,path VARCHAR2(1024),secure VARCHAR2(1),version BINARY_INTEGER );

Page 160: 9ib_SQL

SQL and PL/SQL Enhancements 3-57

Cookies in UTL_HTTP (continued)…CREATE SEQUENCE session_id;

REM Retrieve cookies from UTL_HTTP

CREATE OR REPLACE FUNCTION save_cookies RETURN BINARY_INTEGER AScookies utl_http.cookie_table;my_session_id BINARY_INTEGER;secure VARCHAR2(1);

BEGIN-- assume that some cookies have been set in previous HTTP request s. utl_http.get_cookies(cookies);SELECT session_id.nextval INTO my_session_id FROM dual;

FOR i in 1..cookies.count LOOPIF (cookies(i).secure) THENsecure := 'Y';ELSEsecure := 'N';END IF;INSERT INTO my_cookies VALUES (my_session_id,

cookies(i).name, cookies(i).value, cookies(i).domain, cookies(i).expire, cookies(i).path, secure, cookies(i).version);

END LOOP;RETURN my_session_id;

END;…

Page 161: 9ib_SQL

SQL and PL/SQL Enhancements 3-58

Cookies in UTL_HTTP (continued)…REM Retrieve cookies from UTL_HTTP

CREATE OR REPLACE PROCEDURE restore_cookies (this_session_id IN BINARY_INTEGER) AS

cookies utl_http.cookie_table;cookie utl_http.cookie;i PLS_INTEGER := 0;

CURSOR c (c_session_id BINARY_INTEGER) ISSELECT * FROM my_cookies WHERE session_id = c_session_id;

BEGIN

FOR r IN c(this_session_id) LOOPi := i + 1;cookie.name := r.name;cookie.value := r.value;cookie.domain := r.domain;cookie.expire := r.expire;cookie.path := r.path;IF (r.secure = 'Y') THEN

cookie.secure := TRUE;ELSE

cookie.secure := FALSE;END IF;cookie.version := r.version;cookies(i) := cookie;

END LOOP;

utl_http.clear_cookies;utl_http.add_cookies(cookies);

END;

Page 162: 9ib_SQL

SQL and PL/SQL Enhancements 3-59

Summary

• In this lesson, you should have learned about:• Bulk bind enhancements• Cursor subqueries• Native compilation of PL/SQL• Internet packages

Page 163: 9ib_SQL

SQL and PL/SQL Enhancements 4-1

Enhancements to LOBs in Oracle9i

Page 164: 9ib_SQL

SQL and PL/SQL Enhancements 4-2

Objectives

After completing this lesson you should be able to describe:

•Migrating LONG to LOB •LOB enhancements in SQL and PL/SQL•LONG API

Page 165: 9ib_SQL

SQL and PL/SQL Enhancements 4-3

Overview

• LOBs or large object datatype was introduced in Oracle 8.0 since they provide better functionality than the LONG datatype.

• It is recommended that existing applications using LONGs should be converted to use LOBsbecause of the added functionality.

• To assist in the migration process LONG API for LOBs has been introduced in Oracle9i.

OverviewThe following are some of the advantages of LOBs over LONGs:�Up to 4 Giga bytes in size vs. 2 Giga bytes in the LONGs�Random piecewise access vs. sequential access�Multiple LOB columns vs. single LONG per table�LOBs can have aggregate data type attributes �Storage flexibility with LOB segments vs. entire LONG being stored in the table itself

Page 166: 9ib_SQL

SQL and PL/SQL Enhancements 4-4

Applications of LOB enhancements

• To facilitate in the migration process of LONG to LOB

• To allow customers to use LOBs in existing applications

• To use LOBs in the place of LONGs in existing code

Page 167: 9ib_SQL

SQL and PL/SQL Enhancements 4-5

Oracle9i LONG to LOB Migration

• ALTER TABLE command has been enhanced to allow the datatype of a LONG column to be modified to CLOB and that of a LONG_RAWcolumn to be modified to BLOB.

• The conversion can be completed using the ALTER TABLE…MODIFY command.

• This works similar to the ALTER TABLE…MOVEcommand.

• During the conversion the space required for both the LONG and the LOB data must be available.

Previous Method for LONG to LOB MigrationOracle8i introduced the new TO_LOB() operator that copies LONG to LOB. The TO_LOB() operator can be used in CREATE TABLE AS subquery and INSERT INTO AS subquery statements, to copy the data from a LONG to a LOBOracle9i LONG to LOB migrationThe ALTER TABLE command can be used to change a LONG to a LOB. Default values can be specified for the LOB column and a LOB storage clause can be specified for storing the LOB segment. The null/not-null constraints of the old LONG column are maintained for the new LOB column. Other ALTER TABLE commands are not allowed within the same command.The new ALTER TABLE… MODIFY command will only modify a LONG or a LONG RAW column to a LOB column. It will not modify a VARCHAR or a RAW column

Page 168: 9ib_SQL

SQL and PL/SQL Enhancements 4-6

Example of LONG to LOB Migration

CREATE TABLE print_media (PRODUCT_ID NOT NULL NUMBER(6),AD_ID NOT NULL NUMBER(6),AD_COMPOSITE BLOB,AD_SOURCETEXT CLOB…PRESS_RELEASE LONG );

ALTER TABLE print_mediaMODIFY ( press_release CLOB):

CREATE TABLE print_media (PRODUCT_ID NOT NULL NUMBER(6),AD_ID NOT NULL NUMBER(6),AD_COMPOSITE BLOB,AD_SOURCETEXT CLOB…PRESS_RELEASE LONG );

ALTER TABLE print_mediaMODIFY ( press_release CLOB):

Example of LONG to LOB MigrationThe "ALTER TABLE MODIFY LONG -> LOB" command works like the "ALTER TABLE MOVE" command. Hence the contents of the table are copied into a new space, and the old space is removed at the operation. This temporarily doubles the space requirements. But the advantage is that after the transformation, the table will not have any embedded Nulls in place of the old LONG column, hence the performance of subsequent DMLs / queries on the table will not deteriorate. During the migration , the redo changes for the table will be logged only if the table has logging on. The redo changes for the column being converted from LONG to LOB are logged only if the storage characteristics of the LOB indicate LOGGING.

Page 169: 9ib_SQL

SQL and PL/SQL Enhancements 4-7

SQL Support for LOB Migration

• SQL functions and operators that accept VARCHAR as arguments accept CLOBs as well

• SQL functions that accept RAW as arguments accept BLOBs as well

Page 170: 9ib_SQL

SQL and PL/SQL Enhancements 4-8

Example of Using Predefined Functions on LOBsIn the above example we are applying the SUBSTR function on the press_release column which is a

CLOB column. We are trying to extract 100 characters starting from the 100th position from this column.

Example of Using Predefined Functions on LOBs

SELECT SUBSTR(press_release, 100, 200) FROM print media;

SELECT SUBSTR(press_release, 100, 200) FROM print media;

Page 171: 9ib_SQL

SQL and PL/SQL Enhancements 4-9

PL/SQL Support for LOB migration

• All predefined functions defined in the STANDARD package such as SUBSTR, INSTRetc. which accept LONG types will now accept CLOBs as well.

• All predefined function accepting LONG RAW, can now accept BLOBs.

• Implicit conversion for LOBs to VARCHARs and RAWs and vice versa is done in assignments and when passing parameters

• A user can define and bind LOB columns as VARCHARs and RAWs

Page 172: 9ib_SQL

SQL and PL/SQL Enhancements 4-10

Implicit Assignment and Parameter Passing to LOBs

• Variables declared as %types of LONG columns are implicitly converted to accept LOBvalues after the long columns are modified LOBs

• LOB, VARCHAR and RAW values can be passed to parameters defined as %types of LONGcolumns after the columns are modified to LOBs

• Users can SELECT a CLOB column into a VARCHAR or a BLOB column into a RAW variable

• Allows built-ins to accept CLOB and BLOB data in addition to VARCHARs and RAWs

Example of Implicit Assignment and Parameter passing to LOBsCREATE TABLE lobtab ( lcol LONG);/*create an anonymous block to r*/

DECLAREvar1 VARCHAR2(100);var2 lobtab.lcol%type;

BEGINSELECT * INTO var2 FROM lobtab;var1 := var2; -- This will change from "VARCHAR := LONG" to -- VARCHAR := CLOBvar2:= var1; -- This will change from "LONG := VARCHAR"

END;

/*change LONG to LOB */ALTER TABLE lobtab MODIFY lcol CLOB;

The anonymous block still compiles because of the implicit conversions of the variables

Page 173: 9ib_SQL

SQL and PL/SQL Enhancements 4-11

Example of Implicit Conversion of LOBs

DECLAREv_clob CLOB;v_char VARCHAR(32500);

BEGINSELECT AD_SOURCETEXT INTO v_clob FROM

print_media WHERE product_id = 501;v_char := rtrim(v_clob);

END;

DECLAREv_clob CLOB;v_char VARCHAR(32500);

BEGINSELECT AD_SOURCETEXT INTO v_clob FROM

print_media WHERE product_id = 501;v_char := rtrim(v_clob);

END;

Page 174: 9ib_SQL

SQL and PL/SQL Enhancements 4-12

Support for LOB Migration in OCI Interface

It is possible to:• Bind VARCHAR2 buffer up to 4 GB in size for INSERT/UPDATE into CLOB column

• Bind RAW buffer up to 4 GB in size for INSERT/UPDATE into BLOB column

• Define a CLOB as VARCHAR2 to SELECT the LOBdata directly into a buffer

• Define a BLOB column as RAW to select the LOB data directly into a buffer

• INSERT/UPDATE in a single piece, or Piecewise or in array mode

LONG APIs for LOBs in OCIIn earlier releases a VARCHAR buffer greater than 4 k cannot be bound to a LOB column. This restriction has been lifted in Oracle9i

REFERENCENote :For more information on OCI functionality please refer to the OCI unit under Development Platforms web class.

Page 175: 9ib_SQL

SQL and PL/SQL Enhancements 4-13

Restrictions to LOB Migration• LOBs are not allowed in clustered tables• The migration of LONG columns for a replicated

table cannot itself be replicated. • Materialized views on the table being migrated

will have to be manually rebuilt• Triggers do not support LOBs in UPDATE OF

clause• If a view has an INSTEAD OF trigger then we

cannot specify strings for INSERT/UPDATE of LOB columns

• Indexes need to be manually rebuilt• Domain indexes on the LONG columns have to

be dropped before migration

Restrictions on LOB Migration• LOBs are not allowed in clustered tables, whereas LONGs are allowed. So if a table is a part of a

cluster, its LONG or LONG RAW column cannot be changed to LOB.• If a table is replicated or has materialized views, and its LONG column is changed to LOB, the

replica tables need to be manually rebuilt.• LOB columns are not allowed in the UPDATE OF list in the update triggers. Hence triggers which

were intended to update LONG columns will become invalid after the column is migrated to a LOB and will not recompile. Also if a view with a LOB column has an instead of trigger which attempts to INSERT/UPDATE into the LOB, the trigger will fail because implicit conversion from LOB is not allowed in instead -of triggers.

• All indexes including functional and domain indexes need to be manually rebuilt . The ALTER TABLE MODIFY LONG -> LOB command acts like a MOVE command, and therefore does not convert the indexes. Domain indexes for the LOB column have to be dropped before altering aLONG column to LOB.

• Domain indexes on the LONG columns have to be dropped before migration

Page 176: 9ib_SQL

SQL and PL/SQL Enhancements 4-14

Other LOB Enhancements

• LOBs in partitioned IOTs• LOBs in Functional Indexes

Other LOB EnhancementsIt is now possible to create LOB columns in partitioned Index Organized Tables (IOTs) . Functional Indexes can be created on LOB columns

Page 177: 9ib_SQL

SQL and PL/SQL Enhancements 4-15

Summary

In this lesson, you should have learned about:• Migrating LONGs to LOBs

• SQL support for migration• PL/SQL support for migration• The LONG API