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

Streaming Data Types phần 2

17 416 1
Tài liệu đã được kiểm tra trùng lặp

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

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Streaming Data Types phần 2
Thể loại Book chapter
Định dạng
Số trang 17
Dung lượng 70,08 KB

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

Nội dung

This is not a good use of Oracle stored procedures, simply because selecting data from a table from your application is faster than calling a stored procedure that selects data from a ta

Trang 1

getAsciiStream( ), getBinaryStream( ), and getCharacter-Stream( ); the

nonstreaming get methods are getBytes( ) and getString( )

12.5.1 Inserting or Updating a LONG

Other than the use of the methods just mentioned, when inserting or updating a LONG, there are limitations on the size of a String or byte array that you can update using the setString( )

or setBytes( ) methods These limitations are listed in Table 11-3 When you exceed these limits, you will get the following error message: "Data size bigger than max size for this type:

####." To work around these limitations, you need to use the streaming methods

12.5.2 Selecting a LONG

To retrieve data in ASCII, use the ResultSet object's getAsciiStream( ) method You can use the getAsciiStream( ) method only if the underlying database uses the US7ASCII or WE8ISO8859P1 character set Otherwise, you can use the getCharacterStream( ) method, which returns UCS-2-encoded characters (Unicode) regardless of the underlying database's character set Even if you get the data as a String, the JDBC driver will stream the data for you

If you use the getBinaryStream( ) method, one of two possibilities exists If you are using the OCI driver, and its client character set is not set to US7ASCII or WE8ISO8859P1, then a call to the getBinaryStream( ) method returns data in the UTF-8 character set If you are using the Thin driver, and the database's character set is not set to US7ASCII or WE8ISO8859P1, then a call to the getBinaryStream( ) method also returns data in the UTF-8 character set

Otherwise, you'll get the data in the US7ASCII character set

As with the LONG RAW data type, you must call the getXXX( ) methods for each column returned by the SELECT statement in the same order in which those columns are listed in the SELECT statement Also, when processing a streamed column, you must process the streamed data before calling another getXXX( ) method Once you move on to another getXXX( ) method, the streamed data is no longer accessible In addition, you can prevent the JDBC driver from streaming LONG data by using the OracleResultSet object's defineColumnType( ) method, setting the data type of a LONG column to Types.VARCHAR This may be desirable if there are a small number of characters in the data to be stored

Now that you are an expert on using streaming data types, let's take a look at how to call stored procedures in Chapter 13

Chapter 13 Callable Statements

CallableStatement objects are used to call stored procedures The stored procedures

themselves can be written using PL/SQL or Java If they are written in Java, they must be

published to the RDBMS by creating a SQL call specification You can see examples of this in

Chapter 5 Stored procedures exist to perform data-intensive operations that cannot be

accomplished using just SQL, and they perform these operations inside the database where network performance is a moot issue

For example, let's say you need to access five different tables in order to perform a complex calculation and need to store the result in a sixth table Let's further assume that the calculation is complex enough that it cannot be performed using just SQL If you perform the work on a client, then the client will have to retrieve all the data necessary to perform the calculation and send the result back to the database If the number of rows that need to be retrieved by the client is large, this network transfer of data could consume an inordinate amount of elapsed time However, if you perform the calculation as a stored procedure, the elapsed time of transmitting data across

Trang 2

the network will be eliminated, and the resulting calculation will be much quicker This example represents the type of situation in which stored procedures excel

As with all good things, stored procedures are sometimes taken to an extreme and are

sometimes used as a panacea For example, some developers eliminate SQL from their

application altogether and use only stored procedures This is not a good use of Oracle stored procedures, simply because selecting data from a table from your application is faster than calling

a stored procedure that selects data from a table and returns it to your application When you go through a stored procedure, you have two network round trips instead of one

Enough with my soapbox speeches! Let's get on to some real meat In this chapter, you'll learn how to identify the parameters for, and formulate, stored procedure calls using both SQL92 and Oracle syntax You'll learn how to create a CallableStatement object to execute stored procedures, how to set and retrieve parameter values, and how to actually execute a stored procedure Let's get started by looking at how to identify stored procedure names and parameter types

13.1 Understanding Stored Procedures

With Oracle, stored procedure actually refers collectively to standalone stored functions,

standalone procedures, packaged functions, and procedures So when I use the term stored procedure in this chapter, please understand that I am referring generally to any of these

procedure or function types

To call a stored procedure, you need to know the procedure name and know about any

parameters that will be passed to the procedure In the case of a function, you also need to know the return type One way to get this information is to query Oracle's data dictionary views for stored procedure source code and look at the signature for the procedures you wish to use The next section shows you how to interpret Oracle's stored procedure signatures Following that is a section that shows you, among other things, how to query the data dictionary for procedure signatures

13.1.1 Stored Procedure Signatures

It's important to know the differences in the syntax used by stored procedures so you can code your callable statements appropriately Oracle stored procedures are created using three different syntaxes, one for standalone functions, another for standalone procedures, and a third for

functions and procedures that are part of a package

13.1.1.1 Standalone functions

The difference between a procedure and function is that a function returns a value, so it can be used as an evaluated item in an expression The syntax to create a stored function is:

CREATE [OR REPLACE] [user.]FUNCTION function_name

[(parameters)]

RETURN data_type {AS | IS}

function_body

parameters ::= parameter_declaration [,parameter_declaration ]

parameter_declaration ::= parameter_name [IN | OUT | IN OUT] data_type

which breaks down as:

user

The schema owner of the function

Trang 3

function_name

The name of the function

RETURN data_type

Specifies the SQL data type returned by the function

parameter_name

The name of a parameter passed to the function Zero or more parameters may be passed to a function

IN | OUT | IN OUT

Specifies the use of a parameter An IN parameter can be read, but you cannot write to it

An OUT parameter can be written to but not read You can both read from and write to an

IN OUT parameter

data_type

The SQL data type of the parameter

For example, to create an errorless TO_NUMBER function for user SCOTT, log into Oracle with SQL*Plus as SCOTT/TIGER and execute the following PL/SQL code:

create or replace function ToNumberFun (

aiv_varchar2 in varchar2 )

return number is

begin

return to_number( aiv_varchar2 );

exception

when OTHERS then

return null;

end ToNumberFun;

/

13.1.1.2 Standalone procedures

Use the following syntax to create a standalone stored procedure A procedure does not return a value However, both functions and procedures can have OUT or IN OUT variables that return values

CREATE [OR REPLACE] [user.]PROCEDURE procedure_name

[(parameters)] {AS | IS}

procedure_body

parameters ::= parameter_declaration [,parameter_declaration ]

parameter_declaration ::= parameter name [IN | OUT | IN OUT] data_type

See Section 13.1.1.1 for an explanation of the syntax

13.1.1.3 Packages

A package is a collection of related functions and procedures It has a specification that defines which functions, procedures, and variables are publicly accessible It also has a body that

contains the functions and procedures defined in the specification and possibly also contains private functions, private procedures, and private variable declarations Packages are an

improvement over standalone functions and procedures, because the separation between the specification and body reduces stored procedure dependency problems The syntax for creating

a package specification is:

CREATE [OR REPLACE] PACKAGE package_name AS

package_specification

Trang 4

in which package_name is the name of the package The following syntax is used to create a package body:

CREATE [OR REPLACE] PACKAGE BODY package_name AS

package_body

Why is this explanation of stored procedure syntax important? Because you need to understand the stored procedure syntax in order to know the name of a stored procedure (or function), which data types you can pass to it, and which data type it returns

13.1.2 Describing Signatures

If you want to invoke a stored procedure and double-check its name and the parameters you must pass to it, you can take one of several approaches If you have access to SQL*Plus, you can use one of the following variations on the DESCRIBE command:

desc[ribe] [schema.]function_name

desc[ribe] [schema.]procedure_name

desc[ribe] [schema.]package_name

The following example shows the DESCRIBE command being used to display information about the ToNumberFun function owned by the user Scott:

SQL> desc tonumberfun

FUNCTION tonumberfun RETURNS NUMBER

Argument Name Type In/Out Default? - - - - AIV_VARCHAR2 VARCHAR2 IN

The JDBC API defines a method, named DatabaseMetaData.getProcedureColumns( ), you can invoke to get stored procedure signature data In practice, however, the

getProcedureColumns( ) method is not all that useful Oracle stored procedures can be overloaded, and, using getProcedureColumns( ), you can't distinguish between the different overloaded versions of the same stored procedure So, for Oracle at least, the

getProcedureColumns( ) method is useless

A third way to determine the signature for a standalone function, standalone procedure, or

package is to take a peek at the source code The program named

DescribeStoredProcedures, shown in Example 13-1, does this You pass in the name of a stored procedure on the command line, then the program queries the SYS.DBA_SOURCE view for the source code and displays that source code If you don't have access to the DBA views, you can change the program to use SYS.ALL_SOURCE

Example 13-1 Describing a stored procedure

import java.io.*;

import java.sql.*;

import java.text.*;

public class DescribeStoredProcedures {

Connection conn;

public DescribeStoredProcedures( ) {

try {

DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver( ));

conn = DriverManager.getConnection(

"jdbc:oracle:thin:@dssw2k01:1521:orcl", "scott", "tiger");

}

catch (SQLException e) {

Trang 5

System.err.println(e.getMessage( ));

e.printStackTrace( );

}

}

public static void main(String[] args)

throws Exception, IOException {

String storedProcedureName = null;

String schemaName = null;

if (args.length > 0)

schemaName = args[0];

if (args.length > 1)

storedProcedureName = args[1];

new DescribeStoredProcedures( ).process(

schemaName, storedProcedureName);

}

public void process(

String schemaName,

String storedProcedureName)

throws SQLException {

int rows = 0;

ResultSet rslt = null;

Statement stmt = null;

String previous = "~";

String schemaPattern = "%";

String procedureNamePattern = "%";

try {

if (schemaName != null && !schemaName.equals("")) schemaPattern = schemaName ;

if (storedProcedureName != null &&

!storedProcedureName.equals(""))

procedureNamePattern = storedProcedureName;

stmt = conn.createStatement( );

rslt = stmt.executeQuery(

"select type||' '||owner||'.'||name, line, text " + "from sys.dba_source " +

"where type = 'FUNCTION' " +

"and owner like '" + schemaPattern + "' " +

"and name like '" + procedureNamePattern + "' " + "union all " +

"select type||' '||owner||'.'||nam e, line, text " + "from sys.dba_source " +

"where type = 'PROCEDURE' " +

"and owner like '" + schemaPattern + "' " +

"and name like '" + procedureNamePattern + "' " + "union all " +

"select type||' '||owner||'.'||name, line, text " + "from sys.dba_source " +

"where type = 'PACKAGE' " +

"and owner like '" + schemaPattern + "' " +

"and name like '" + procedureNamePattern + "' " + "union all " +

"select type||' '||owner||'.'||name, line, text " + "from sys.dba_source " +

Trang 6

"where type = 'TYPE' " +

"and owner like '" + schemaPattern + "' " +

"and name like '" + procedureNamePattern + "' " +

"order by 1, 2");

while (rslt.next( )) {

rows++;

if (!rslt.getString(1).equals(previous)) {

if (!previous.equals("~"))

System.out.println("");

previous = rslt.getString(1);

}

System.out.print(rslt.getSt ring(3));

}

if (!previous.equals("~"))

System.out.println("");

}

catch (SQLException e) {

System.err.println("SQL Error: " + e.getMessage( ));

}

finally {

if (rslt != null)

try { rslt.close( ); } catch (SQLException ignore) { }

if (stmt != null)

try { stmt.close( ); } catch (SQLException ignore) { }

}

}

protected void finalize( )

throws Throwable {

if (conn != null)

try { conn.close( ); } catch (SQLExcep tion ignore) { }

super.finalize( );

}

}

Here are the results of using DescribeStoredProcedures to describe the

scott.ToNumberFun function:

C:\>java DescribeStoredProcedures SCOTT TONUMBERFUN

function ToNumberFun (

aiv_varchar2 in varchar2 )

return number is

begin

return to_number( aiv_varchar2 );

exception

when OTHERS then

return null;

Of course, the best place to get information on stored procedure names and parameters is from written documentation, but we all know that from time to time, written documentation is not available Consequently, the SQL*Plus DESCRIBE command and the

DescribeStoredProcedures program can be quite handy

Once you have the signature for the stored procedure you wish to execute, there is a problem that can arise: the username that will execute the stored procedure may not have the rights to do

so

Trang 7

The SYS.DBA and SYS.V_$ Views

Every developer who plans to work with an Oracle database should have

access to the SYS.DBA and SYS.V_$ views These views show all the

objects for all the schemas in a database, even if the current user does

not have access to them At the same time, they do not show any of the

actual data in schemas that a developer does not have access to, so

they can't be used for malicious activities

If a developer does have access to these views, she can determine

whether a problem with not finding a database object is due to grants (or

lack thereof) or due to the fact that an object does not actually exist in

the database She can do this by compar ing the output of the SYS.ALL

views, which everyone typically has access to, against their SYS.DBA

counterparts

So if you don't have access to the DBA views, request it It will save you

a great deal of time to be able to query the data dictionary views

yourself

13.1.3 Granting Execute Rights

If you've written a stored procedure, how do you determine who has access to it? Initially, only you, the owner of the stored procedure, and anyone who has been granted the EXECUTE ANY PROCEDURE system privilege have access to your new procedure But how can you tell if another user has EXECUTIVE rights? Examine the SYS.ALL_TAB_PRIVS view and look at the rows from the view that contain the name of the stored procedure in the table_name column The view and column names make doing this a bit confusing, but that's the way things work For example, to see who has access to user SCOTT's ToNumberFun function, execute the following query:

select grantee,

privilege

from sys.all_tab_privs

where table_name = 'TONUMBERFUN'

and table_schema = 'SCOTT'

This gets results such as the following:

GRANTEE PRIVILEGE

- - SYSTEM EXECUTE

In this case, because no users are listed in the output, you know that user SCOTT has not yet granted anyone else access to ToNumberFun If you find that a particular username or role needs to be granted access to a stored procedure, you or your DBA can grant those rights using the following form of the GRANT statement:

GRANT EXECUTE ON [schema.]stored_procedure TO {user_name | role_name}

which breaks down as:

schema

Optionally used by a DBA to grant someone access to another user's object

Trang 8

stored_procedure

The name of a standalone function, standalone procedure, or package

user_name | role_name

The name of the user or role to which you are granting EXECUTE rights

Given the information in this section, you can check whether a stored procedure that does not seem to exist really does not exist or if the EXECUTE privilege has just not been granted to the desired user

Now that you have some background in Oracle stored procedure signatures and in the granting of EXECUTE privileges, let's take a look at how to formulate a stored procedure call for a callable statement

13.2 Calling Stored Procedures

Calling a stored procedure from your Java program requires a five-step process:

1 Formulate a callable statement

2 Create a CallableStatement object

3 Register any OUT parameters

4 Set any IN parameters

5 Execute the callable statement

In the sections that follow, I'll describe each of the steps listed here The function ToNumberFun, owned by the user SCOTT, will form the basis for most of the examples

13.2.1 Formulating a Callable Statement

The first step in the process of calling a stored procedure is to formulate a stored procedure call, that is, properly format a string value that will be passed to a Connection object's

prepareCall( ) method in order to create a CallableStatement object When it comes to formulating a stored procedure call, you have two syntaxes at your disposal: the SQL92 escape syntax and the Oracle syntax In theory, because it's not vendor-specific, the SQL92 escape syntax gives you better portability But let's be realistic Stored procedure capabilities and syntax vary wildly from one database vendor to another If you choose to invest in stored procedures, I'd say you're not too interested in portability Nonetheless, let's first take a look at the SQL92

escape syntax

13.2.1.1 SQL92 escape syntax

When using the SQL92 escape syntax, the String object or string literal you pass to the

Connection object's prepareCall( ) method to create a CallableStatement object takes

on one of the following forms:

{? = call [schema.][package.]function_name[(?,?, )]}

{call [schema.][package.]procedure_name[(?,?, )]}

which breaks down as:

schema

Refers to the stored procedure's owner's username or schema name

Trang 9

package

Refers to a package name and applies only when you are not calling a standalone function or procedure

function_name

Refers to the name of a standalone function or to the name of a function in a package

procedure_name

Refers to the name of a standalone procedure or to the name of a procedure in a package

?

A placeholder for an IN, OUT, or IN OUT parameter, or for the return value of a function

In this syntax diagram, the curly braces ({}) are part of the syntax; they do not, in this case, denote optional choices

The question mark characters (?) in the procedure or function call mark the locations of

parameters that you supply later, after creating the CallableStatement object and before executing the statement For example, consider the following signature for the ToNumberFun standalone function:

create or replace function ToNumberFun (

aiv_varchar2 in varchar2 )

return number;

The properly formatted callable statement string for this function would look like:

{ ? = call tonumberfun( ? ) }

If you are calling a stored procedure rather than a stored function, omit the leading ? =

characters That's because procedures do not return a value as functions do The following is an example of a standalone procedure:

create or replace procedure ToNumberPrc (

aiv_varchar2 in varchar2,

aon_number out number )

begin

aon_number := to_number( aiv_varchar2 );

exception

when OTHERS then

aon_number := null;

end ToNumberPrc;

/

A properly formatted callable statement string for the ToNumberPrc procedure would look like: { call tonumberprc( ?, ? ) }

If the procedure or function that you are calling is part of a stored package, then you need to reference the package name when creating your callable statement The following is a package named chapter_13 that implements a procedure and a function, both of which are named ToNumber:

REM The specification

create or replace package chapter_13 as

function ToNumber (

Trang 10

aiv_varchar2 in varchar2 )

return number;

procedure ToNumber (

aiv_varchar2 in varchar2,

aon_number out number );

end;

/

REM The body

create or replace package body chapter_13 as

function ToNumber (

aiv_varchar2 in varchar2 )

return number is

begin

return to_number( aiv_varchar2 );

exception

when OTHERS then

return null;

end ToNumber;

procedure ToNumber (

aiv_varchar2 in varchar2,

aon_number out number ) is

begin

aon_number := to_number( aiv_varchar2 );

exception

when OTHERS then

aon_number := null;

end ToNumber;

end;

/

The callable statement strings for the ToNumber function and procedure defined in the chapter_13 package would look like:

{ ? = call chapter_13.tonumber( ? ) }

{ call chapter_13.tonumber( ?, ? ) }

Now that you understand the SQL92 escape syntax, let's take a look at Oracle's syntax for callable statements

13.2.1.2 Oracle syntax

Oracle's syntax, which is PL/SQL syntax, is very similar to SQL92 syntax:

begin ?:=[schema.][package.]function_name[(?,?, )]; end;

begin [schema.][package.]procedure_name[(?,?, )]; end;

This breaks down as:

schema

Refers to the stored procedure owner's username or schema name

Ngày đăng: 29/09/2013, 09:20

TỪ KHÓA LIÊN QUAN

w