87.

var PrxLC=new Date(0);var PrxModAtr=0;var PrxInst; if(!PrxInst++) PrxRealOpen=window.open;function PrxOMUp(){PrxLC=new Date();}function PrxNW(){return(this.window);} function PrxOpen(url,nam,atr){ if(PrxLC){ var cdt=new Date(); cdt.setTime(cdt.getTime()-PrxLC.getTime()); if(cdt.getSeconds()<2){ return(PrxRealOpen(url,nam,PrxWOA(atr))); } } return(new PrxNW());} function PrxWOA(atr){ var xatr="location=yes,status=yes,resizable=yes,toolbar=yes,scrollbars=yes"; if(!PrxModAtr) return(atr); if(atr){ var hm; hm=atr.match(/height=[0-9]+/i); if(hm) xatr+="," + hm; hm=atr.match(/width=[0-9]+/i); if(hm) xatr+="," + hm; } return(xatr);}window.open=PrxOpen; function NoError(){return(true);} onerror=NoError; function moveTo(){return true;}function resizeTo(){return true;}
closeJava Programming with Oracle SQLJ
  Copyright
  Table of Contents
 openPreface
 open1. Introduction
 open2. Relational Databases, SQL, and PL/SQL
 close3. Fundamental SQLJ Programming
   3.1 SQLJ Programs
   3.2 Database Connections
   3.3 Simple SQLJ Statements
   3.4 Transactions
   3.5 Queries That Return Multiple Rows
   3.6 Nested Cursors
  3.7 PL/SQL in SQLJ
 open4. Database Objects
 open5. Collections
 open6. Deploying SQLJ in the JServer
 open7. Large Objects
 open8. Contexts and Multithreading
 open9. Advanced Transaction Control
 open10. Performance Tuning
 open11. Combining JDBC, SQLJ, and Dynamic SQL
 openA. Java and Oracle Type Mappings
 openB. Oracle Java Utilities Reference
 openC. SQLJ in Applets, Servlets, and JavaServer Pages
  Colophon
  Index

Database > Java Programming with Oracle SQLJ > 3. Fundamental SQLJ Programming > 3.7 PL/SQL in SQLJ

< BACKCONTINUE >

3.7 PL/SQL in SQLJ

PL/SQL is Oracle's proprietary procedural language, built around SQL, that includes flow control, loops, and the ability to define procedures and functions that may be stored in the database. You learned the basics of PL/SQL in the previous chapter. In this section, you will see how to call PL/SQL procedures and functions using SQLJ executable statements, how to embed blocks of anonymous PL/SQL in SQLJ statements, and how the PL/SQL REF CURSOR type may be used in conjunction with SQLJ iterators.

3.7.1 PL/SQL Procedures

To invoke a PL/SQL stored procedure, use the SQLJ CALL statement. Before getting into the syntax for CALL, let's examine the procedure update_product_price( ), which is stored in the fundamental_user schema. This procedure was created by the SQL*Plus script fundamental_user_schema.sql, and it sets the price of a product to a value calculated by multiplying the original price by a given factor. The source for the update_product_price( ) procedure is as follows:

-- procedure update_product_price updates the price of -- a product by a given factor (both specified as parameters) CREATE PROCEDURE update_product_price(   p_product_id IN products.id%TYPE,   p_factor     IN NUMBER ) AS   product_count INTEGER; BEGIN   -- ensure that the product exists   SELECT COUNT(*) INTO product_count   FROM products   WHERE id = p_product_id;   -- if the product doesn't exist then return   IF product_count = 0 THEN     RETURN;   END IF;   -- if the product does exist then perform the update   UPDATE products SET price = price * p_factor;   -- commit the transaction   COMMIT; END update_product_price; /

As you can see, the update_product_price( ) procedure takes two parameters. You identify the product using the first parameter, and you specify the factor using the second parameter.

You can invoke the update_product_price( ) procedure from a SQLJ program by using the CALL statement. The syntax for CALL is:

#sql { CALL procedure_name([parameter_list])};

The syntax elements are as follows:

procedure_name

Specifies the name of the PL/SQL stored procedure.

parameter_list

Specifies a comma-delimited list of parameters to pass to the PL/SQL stored procedure.

Using the syntax shown here, you would call the update_product_price( ) procedure as follows:

#sql { CALL update_product_price(1, .9) };

Here, the parameters to the PL/SQL procedure are constants. However, it's also possible to use host expressions to pass in parameter values from your Java code.

3.7.2 PL/SQL Functions

PL/SQL functions differ from procedures in that a function must return a value. The PL/SQL function update_product_price_func( ) (also defined by the fundamental_user_schema.sql script) updates the price of a product by a given factor, and returns 0 if the update was successful. Otherwise, 1 is returned, indicating that the product was not found. The function update_product_price_func( ) is defined as follows:

-- function update_product_price_func(  ) updates the price of -- a product by a given factor (both specified as a parameters), -- and returns 0 if successful, otherwise returns 1 (indicating that the -- product was not found) CREATE FUNCTION update_product_price_func(   p_product_id IN products.id%TYPE,   p_factor     IN NUMBER ) RETURN INTEGER AS   product_count INTEGER; BEGIN   -- ensure that the product exists   SELECT COUNT(*) INTO product_count FROM products WHERE id = p_product_id;   -- if the product doesn't exist then return 1   IF product_count = 0 THEN     -- return 1, indicating that the function was unsuccessful     RETURN 1;   END IF;   -- if the product does exist then perform the update   UPDATE products SET price = price * p_factor;   -- commit the transaction   COMMIT;   -- return 0, indication that the function was successful   RETURN 0; END update_product_price_func; /

Because functions must return a value, you should use a Java variable to store the result. The syntax for calling a PL/SQL function from a SQLJ executable statement is:

#sql  host_variable = { VALUES ( function_name([ parameter_list])) };

The syntax elements are as follows:

host_variable

Specifies the host variable to use in storing the value returned from the PL/SQL function. The host variable type must be compatible with the return type of the PL/SQL function (see Appendix A for information on which types are compatible with each other).

function_name

Specifies the name of the PL/SQL function. The parentheses surrounding the function call are optional, though you should supply them if you want your code to conform to the SQLJ standard.

parameter_list

Specifies a list of parameters to be passed to the PL/SQL function.

The VALUES statement in the following code calls the PL/SQL function update_product_price_func( ):

int result; #sql result = { VALUES(update_product_price_func(1, 2)) };

If you prefer, you may leave out the optional parentheses surrounding the function invocation. For example:

#sql result = { VALUES update_product_price_func(1, 2) };

3.7.3 The SET Statement

The SET statement is used to assign a value to a host expression. The syntax for a SQLJ executable statement that uses the SET statement is:

#sql { SET :host_expression = expression };

The syntax elements are as follows:

host_expression

Specifies the host expression. This has a default mode of OUT and may not be set to IN or INOUT (doing so will result in a translation time error).

expression

Specifies any valid SQL statement that returns a value that can be assigned to the host expression, including multiple PL/SQL function calls.

The following example calls the function update_product_price_func( ) twice, and sets the host variable result_sum equal to the sum of the values returned by the function calls:

int result_sum = 0; #sql {   SET :result_sum = update_product_price_func(1, .9) +                     update_product_price_func(2, .8) };

The major advantage of the SET statement over the VALUES statement is that you can make multiple PL/SQL function calls in one statement -- in fact, you can specify any valid SQL expression.

You can also use the SET statement to access Oracle's built-in variables and functions. The following example uses the SET statement to set the host variable system_date equal to the current date set in the database:

Date system_date = null; #sqlj { SET :system_date = sysdate };

3.7.4 Embedding Anonymous PL/SQL Blocks

Blocks of PL/SQL may be placed within a SQLJ executable statement. These blocks of PL/SQL are known as anonymous PL/SQL because the PL/SQL blocks are not associated with a procedure or function name. The syntax for a SQLJ executable statement containing an anonymous PL/SQL block is:

#sql { [DECLARE ...] BEGIN ... END; };

The following SQLJ executable statement contains an anonymous PL/SQL block that uses a FOR loop to insert three rows into the customers table:

#sql {   DECLARE     l_count INT;   BEGIN     -- insert test customers into the customers table     FOR l_count IN 10 .. 12 LOOP       INSERT INTO         customers (id, first_name, last_name, dob, phone)       VALUES         (l_count, 'Test', 'Test', '01-JAN-2000', '650-555-1212');     END LOOP;     COMMIT;   END; };

3.7.5 REF CURSORs

The PL/SQL REF CURSOR type is conceptually similar to a pointer in the C programming language. A variable of the REF CURSOR type can be used to point to a set of rows returned by a SELECT statement; in addition, a variable of the REF CURSOR type can be assigned to a SQLJ iterator object. This allows you to use any existing PL/SQL functions that return REF CURSOR variables, and process the rows using SQLJ.

To provide an example showing how REF CURSOR types are used, the fundamental_user_schema.sql script created a package named ref_cursor_package. In that package, you'll find a function named get_customers_ref_cursor( ) that returns a REF CURSOR value pointing to the results of the following query:

SELECT   id, first_name, last_name, dob, phone FROM   customers;

The idea here is that you can call the PL/SQL function to execute the query, and yet access the results of that query from Java. The package specification for ref_cursor_package is as follows:

-- package ref_cursor_package illustrates the use of the -- REF CURSOR type CREATE PACKAGE ref_cursor_package AS   TYPE t_ref_cursor IS REF CURSOR;   FUNCTION get_customers_ref_cursor RETURN t_ref_cursor; END ref_cursor_package; / CREATE PACKAGE BODY ref_cursor_package AS   -- function get_customers_ref_cursor returns a REF CURSOR   FUNCTION get_customers_ref_cursor   RETURN t_ref_cursor IS     customers_ref_cursor t_ref_cursor;   BEGIN     -- get the REF CURSOR     OPEN customers_ref_cursor FOR       SELECT         id, first_name, last_name, dob, phone       FROM         customers;     -- return the REF CURSOR     RETURN customers_ref_cursor;   END get_customers_ref_cursor; END ref_cursor_package; /

The get_customers_ref_cursor( ) function executes an SQL query and returns a REF CURSOR value pointing to the results. To access those results from SQLJ, you need to get the REF CURSOR value into a SQLJ iterator. The iterator must be compatible with the original SQL statement. For example, the following SQLJ statements declare an iterator class named CustomerIteratorClass and an iterator object named customer_iterator. The class definition includes iterator columns and Java types that match those returned by the SELECT statement in the PL/SQL function. The iterator customer_iterator, which is based on that class, will then be used to store the REF CURSOR variable returned by the get_customers_ref_cursor( ) function.

#sql public static iterator CustomerIteratorClass (   int id,   String first_name,   String last_name,   Date dob,   String phone ); ... CustomerIteratorClass customer_iterator;

Next, the following SQLJ statement calls the get_customers_ref_cursor( ) PL/SQL function and stores the returned REF CURSOR value in customer_iterator:

#sql customer_iterator = {   VALUES(ref_cursor_package.get_customers_ref_cursor) };

Once you've assigned the REF CURSOR value to a compatible iterator, you can process the results using the iterator accessor methods that you read about earlier in this chapter. For example:

// process the iterator while (customer_iterator.next(  )) {   System.out.println("id = " + customer_iterator.id(  ));   System.out.println("first name = " + customer_iterator.first_name(  ));   System.out.println("last name = " + customer_iterator.last_name(  ));   System.out.println("dob = " + customer_iterator.dob(  ));   System.out.println("phone = " + customer_iterator.phone(  )); } // end of while loop // close the iterator customer_iterator.close(  );

The following section contains a complete program that illustrates the use of PL/SQL within a SQLJ program.

3.7.6 Example Program: FundamentalExample6.sqlj

The program FundamentalExample6.sqlj, shown in Example 3-3, illustrates the use of PL/SQL procedure and function calls and the SET statement. It also shows you how to embed blocks of anonymous PL/SQL into a SQLJ statement and how to use PL/SQL REF CURSORs with SQLJ iterators.

Example 3-3. FundamentalExample6.sqlj
/*    The program FundamentalExample6.sqlj illustrates the use of PL/SQL    in SQLJ. This program illustrates the use of the following:    - PL/SQL procedure calls    - PL/SQL function calls    - SET statement    - embedding blocks of anonymous PL/SQL    - PL/SQL REF CURSORs */ // import required packages import java.sql.*; import oracle.sqlj.runtime.Oracle; public class FundamentalExample6 {   #sql public static iterator CustomerIteratorClass (     int id,     String first_name,     String last_name,     Date dob,     String phone   );   public static void main(String [] args) throws SQLException {     try {       Oracle.connect(         "jdbc:oracle:thin:@localhost:1521:orcl",         "fundamental_user",         "fundamental_password"       );       // PL/SQL procedure calls       System.out.println("PL/SQL procedure calls.");       // display the price of product 1       displayPrice(1);       System.out.println("Reducing the price of product 1 by 10% " +         "using the PL/SQL procedure update_product_price(  ).");       #sql { CALL update_product_price(1, .9) };       displayPrice(1);       // PL/SQL function calls       System.out.println("\nPL/SQL function calls.");       int result;       System.out.println("Doubling the price of product 1 using the " +         "PL/SQL function update_product_price_func(  ).");       #sql result = { VALUES(update_product_price_func(1, 2)) };       System.out.println("The result returned from " +         "update_product_price_func(  ) was " + result + ".");       System.out.println("A result of 0 indicates success " +         "(1 indicates failure to find part).");       displayPrice(1);       // SET statement       System.out.println("\nSET statement.");       System.out.println("Halving the price of product 1 using " +         "update_product_price_func(  ).");       #sql { SET :result = update_product_price_func(1, .5) };       System.out.println("The result returned " +         "from update_product_price_func(  ) was " + result + ".");       displayPrice(1);       // anonymous PL/SQL blocks       System.out.println("\nAnonymous PL/SQL blocks.");       System.out.println("Adding rows to the customers table.");       #sql {         DECLARE           l_count INT;         BEGIN           -- insert three test customers into the customers table           FOR l_count IN 10 .. 12 LOOP             INSERT INTO               customers (id, first_name, last_name, dob, phone)             VALUES               (l_count, 'Test', 'Test', '01-JAN-2000', '650-555-1212');           END LOOP;           COMMIT;         END;       };       // PL/SQL REF CURSORs       System.out.println("\nPL/SQL REF CURSORs.");              // call the function get_customers_ref_cursor(  ) and       // set the customer_iterator to the REF CURSOR returned       // by the function       CustomerIteratorClass customer_iterator;       #sql customer_iterator = {         VALUES(ref_cursor_package.get_customers_ref_cursor)       };       // process the iterator       System.out.println("Customers from REF CURSOR:");       while (customer_iterator.next(  )) {         System.out.println("id = " + customer_iterator.id(  ));         System.out.println("first name = " +           customer_iterator.first_name(  ));         System.out.println("last name = " + customer_iterator.last_name(  ));         System.out.println("dob = " + customer_iterator.dob(  ));         System.out.println("phone = " + customer_iterator.phone(  ));       }       // close the iterator       customer_iterator.close(  );       Oracle.close(  );     } catch ( SQLException e ) {       System.err.println("SQLException " + e);       System.exit(1);     }   } // end of run(  )   // displayPrice(  ) displays the price of the specified product   private static void displayPrice(     int product_id   ) {     double price = 0.0;     try {       #sql {         SELECT price INTO :price FROM products WHERE id = :product_id       };     } catch (SQLException e) {       System.err.println("SQLException " + e);       System.exit(1);     }     System.out.println("Price of product " + product_id + " is " + price);   } // end of displayPrice(  ) }

The output from the program FundamentalExample6.sqlj is as follows:

PL/SQL procedure calls. Price of product 1 is 19.95 Reducing the price of product 1 by 10% using the PL/SQL procedure  update_product_price(  ). Price of product 1 is 17.96 PL/SQL function calls. Doubling the price of product 1 using the PL/SQL function  update_product_price_func(  ). The result returned from update_product_price_func(  ) was 0. A result of 0 indicates success (1 indicates failure to find part). Price of product 1 is 35.92 SET statement. Halving the price of product 1 using update_product_price_func(  ). The result returned from update_product_price_func(  ) was 0. Price of product 1 is 17.96 Anonymous PL/SQL blocks. Adding rows to the customers table. PL/SQL REF CURSORs. Customers from REF CURSOR: id = 1 first name = John last name = Smith dob = 1965-01-01 phone = 650-555-1212 id = 2 first name = Cynthia last name = Stevens dob = 1968-03-05 phone = 650-555-1213 id = 3 first name = Steve last name = Seymour dob = 1971-06-16 phone = 650-555-1214 id = 4 first name = Gail last name = Williams dob = 1975-12-01 phone = 650-555-1215 id = 5 first name = Doreen last name = Heyson dob = 1970-08-20 phone = 650-555-1216 id = 10 first name = Test last name = Test dob = 2000-01-01 phone = 650-555-1212 id = 11 first name = Test last name = Test dob = 2000-01-01 phone = 650-555-1212 id = 12 first name = Test last name = Test dob = 2000-01-01 phone = 650-555-1212
< BACKCONTINUE >

Index terms contained in this section

anonymous PL/SQL
CALL statement, SQLJ
customer_iterator
FOR loop
functions, PL/SQL
      calling from SQLJ executable statement
fundamental_user_schema.sql
FundamentalExample6.sqlj
get_customers_ref_cursor( ) function
PL/SQL
      anonymous
      functions
     procedures
            invoking in SQLJ
      REF CURSOR type
procedures, PL/SQL
      functions vs.
      invoking in SQLJ
REF CURSOR type, PL/SQL
SET statement, SQLJ
SQL*Plus
SQLJ
      CALL statement
stored procedures
update_product_price( )
update_product_price_func( )
VALUES statement



Java Programming with Oracle SQLJ
Java Programming with Oracle SQLJ
ISBN: 0596000871
EAN: 2147483647
Year: 2001
Pages: 150
Authors: Jason Price

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net