Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 50 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
50
Dung lượng
168,8 KB
Nội dung
ORA-06571: Function TOTAL_COMP does not guarantee not to
update database
As discussed in
Section 17.7, "Realities: Calling PL/SQL Functions in SQL", it can be very difficult
at times (and sometimes impossible) to avoid this error. In other situations, however, there is an easy
resolution (certainly do check the above list of restrictions).
Previous: 17.3
Requirements for Stored
Functions in SQL
Oracle PL/SQL
Programming, 2nd Edition
Next: 17.5 Calling
Packaged Functions in SQL
17.3 Requirements for Stored
Functions in SQL
Book Index
17.5 Calling Packaged
Functions in SQL
The Oracle Library
Navigation
Copyright (c) 2000 O'Reilly & Associates. All rights reserved.
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Previous: 17.4 Restrictions
on PL/SQL Functions in
SQL
Chapter 17
Calling PL/SQL Functions in
SQL
Next: 17.6 Column/
Function Name Precedence
17.5 Calling Packaged Functions in SQL
As I describe in Chapter 16, Packages, the specification and body of a package are distinct; a
specification can (and must) exist before its body has been defined. This feature of packages makes
life complicated when it comes to calling functions in SQL. When a SELECT statement calls a
packaged function, the only information available to it is the package specification. Yet it is the
contents of the package body which determine whether that function is valid for execution in SQL.
The consequence of this structure is that you will have to add code to your package specification in
order to enable a packaged function for calling in SQL.
To use the official lingo, you must explicitly "assert" the purity level (the extent to which a function
is free of side effects) of a stored function in a package specification. The Oracle Server can then
determine when the package body is compiled whether the function violates that purity level. If so, an
error will be raised and you then face the sometimes daunting task of figuring out where and how the
violation occurs.
You assert a purity level for a function with the RESTRICT_REFERENCES pragma, explored in the
next section.
17.5.1 The RESTRICT_REFERENCES Pragma
As I've mentioned, a pragma is a special directive to the PL/SQL compiler. If you have ever created a
programmer-defined, named exception, you have already encountered your first pragma. In the case
of the RESTRICT_REFERENCES pragma, you are telling the compiler the purity level you believe
your function meets or exceeds.
You need a separate pragma statement for each packaged function you wish to use in a SQL
statement, and it must come after the function declaration in the package specification (you do not
specify the pragma in the package body).
To assert a purity level with the pragma, use the following syntax:
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
PRAGMA RESTRICT_REFERENCES
(function_name, WNDS [, WNPS] [, RNDS] [, RNPS])
where function_name is the name of the function whose purity level you wish to assert, and the four
different codes have the following meanings:
WNDS
Writes No Database State. Asserts that the function does not modify any database tables.
WNPS
Writes No Package State. Asserts that the function does not modify any package variables.
RNDS
Reads No Database State. Asserts that the function does not read any database tables.
RNPS
Reads No Package State. Asserts that the function does not read any package variables.
Notice that only the WNDS level is mandatory in the pragma. That is consistent with the restriction
that stored functions in SQL may not execute an UPDATE, INSERT, or DELETE statement. All
other states are optional. You can list them in any order, but you must include the WNDS argument.
No one argument implies another argument. I can write to the database without reading from it. I can
read a package variable without writing to a package variable.
Here is an example of two different purity level assertions for functions in the company_financials
package:
PACKAGE company_financials
IS
FUNCTION company_type (type_code_in IN VARCHAR2)
RETURN VARCHAR2;
FUNCTION company_name (company_id_in IN company.
company_id%TYPE)
RETURN VARCHAR2;
PRAGMA RESTRICT_REFERENCES (company_type, WNDS, RNDS,
WNPS, RNPS);
PRAGMA RESTRICT_REFERENCES (company_name, WNDS, WNPS,
RNPS);
END company_financials;
In this package, the company_name function reads from the database to obtain the name for the
specified company. Notice that I placed both pragmas together at the bottom of the package
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
specification the pragma does not need to immediately follow the function specification. I also
went to the trouble of specifying the WNPS and RNPS arguments for both of the functions. Oracle
Corporation recommends that you assert the highest possible purity levels so that the compiler will
never reject the function unnecessarily.
NOTE: If a function you want to call in SQL calls a procedure in a package, you must
also provide a RESTRICT_REFERENCES pragma for that procedure. You can't call
the procedure directly in SQL, but if it is going to be executed indirectly from within
SQL, it still must follow the rules.
17.5.1.1 Pragma violation errors
If your function violates its pragma, you will receive the PLS-00452 error. Suppose, for example, that
the body of the company_financials package looks like this:
CREATE OR REPLACE PACKAGE BODY company_financials
IS
FUNCTION company_type (type_code_in IN VARCHAR2)
RETURN VARCHAR2
IS
v_sal NUMBER;
BEGIN
SELECT sal INTO v_sal FROM emp WHERE empno = 1;
RETURN 'bigone';
END;
FUNCTION company_name (company_id_in IN company.
company_id%TYPE)
RETURN VARCHAR2
IS
BEGIN
UPDATE emp SET sal = 0;
RETURN 'bigone';
END;
END company_financials;
/
When I attempt to compile this package body I will get the following error:
3/4 PLS-00452: Subprogram 'COMPANY_TYPE' violates its
associated pragma
because the company_type function reads from the database and I have asserted the RNDS purity
level. If I remove that silly SELECT statement, I will then receive this error:
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
11/4 PLS-00452: Subprogram 'COMPANY_NAME' violates its
associated pragma
because the company_name function updates the database and I have asserted the WNDS level. You
will sometimes look at your function and say: "Hey, I absolutely do not violate my purity level. There
is no UPDATE, DELETE, or UPDATE around." Maybe not. But there is a good chance that you are
calling a built-in package or in some other way breaking the rules.
17.5.2 Asserting Purity Level with Package Initialization Section
If your package contains an initialization section (executable statements after a BEGIN statement in
the package body), you must also assert the purity level of that section. The initialization section is
executed automatically the first time any package object is referenced. So if a packaged function is
used in a SQL statement, it will trigger execution of that code. If the initialization section modifies
package variables or database information, the compiler needs to know about that through the
pragma.
You can assert the purity level of the initialization section either explicitly or implicitly. To make an
explicit assertion, use the following variation of the pragma RESTRICT_REFERENCES:
PRAGMA RESTRICT_REFERENCES
(package_name, WNDS, [, WNPS] [, RNDS] [, RNPS])
Instead of specifying the name of the function, you include the name of the package itself, followed
by all the applicable state arguments. In the following argument I assert only WNDS and WNPS
because the initialization section reads data from the configuration table and also reads the value of a
global variable from another package (session_pkg.user_id).
PACKAGE configure
IS
PRAGMA RESTRICT_REFERENCES (configure, WNDS, WNPS);
user_name VARCHAR2(100);
END configure;
PACKAGE BODY configure
IS
BEGIN
SELECT lname || ', ' || fname INTO user_name
FROM user_table
WHERE user_id = session_pkg.user_id;
END configure;
Why can I assert the WNPS even though I do write to the user_name package variable? The answer
is that it's a variable from this same package, so the action is not considered a side effect.
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
You can also implicitly assert the purity level of the package's initialization section by allowing the
compiler to infer that level from the purity level(s) of all the pragmas for individual functions in the
package. In the following version of the company package, the two pragmas for the functions allow
the Oracle Server to infer a combined purity level of RNDS and WNPS for the initialization section.
This means that the initialization section cannot read from the database and cannot write to a package
variable.
PACKAGE company
IS
FUNCTION get_company (company_id_in IN VARCHAR2)
RETURN company%ROWTYPE;
FUNCTION deactivate_company (company_id_in IN company.
company_id%TYPE)
RETURN VARCHAR2;
PRAGMA RESTRICT_REFERENCES (get_company, RNDS, WNPS);
PRAGMA RESTRICT_REFERENCES (deactivate_name, WNPS);
END company;
Generally, you are probably better off providing an explicit purity level assertion for the initialization
section. This makes it easier for those responsible for maintaining the package to understand both
your intentions and your understanding of the package.
Previous: 17.4 Restrictions
on PL/SQL Functions in
SQL
Oracle PL/SQL
Programming, 2nd Edition
Next: 17.6 Column/
Function Name Precedence
17.4 Restrictions on PL/SQL
Functions in SQL
Book Index
17.6 Column/Function Name
Precedence
The Oracle Library
Navigation
Copyright (c) 2000 O'Reilly & Associates. All rights reserved.
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Previous: 17.5 Calling
Packaged Functions in SQL
Chapter 17
Calling PL/SQL Functions in
SQL
Next: 17.7 Realities:
Calling PL/SQL Functions
in SQL
17.6 Column/Function Name Precedence
If your function has the same name as a table column in your SELECT statement and it has no
parameters, then the column takes precedence over the function.
The employee table has a column named "salary." Suppose you create a function named salary as
well:
CREATE TABLE employee (employee_id NUMBER, , salary
NUMBER, );
FUNCTION salary RETURN NUMBER;
Then a SELECT statement referencing salary always refers to the column and not the function:
SELECT salary INTO calculated_salary FROM employee;
If you want to override the column precedence, you must qualify the name of the function with the
name of the schema that owns the function, as follows:
SELECT scott.salary INTO calculated_salary FROM employee;
This now executes the function instead of retrieving the column value.
Previous: 17.5 Calling
Packaged Functions in SQL
Oracle PL/SQL
Programming, 2nd Edition
Next: 17.7 Realities:
Calling PL/SQL Functions
in SQL
17.5 Calling Packaged
Functions in SQL
Book Index
17.7 Realities: Calling PL/
SQL Functions in SQL
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
The Oracle Library
Navigation
Copyright (c) 2000 O'Reilly & Associates. All rights reserved.
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Previous: 17.6 Column/
Function Name Precedence
Chapter 17
Calling PL/SQL Functions in
SQL
Next: 17.8 Examples of
Embedded PL/SQL
17.7 Realities: Calling PL/SQL Functions in SQL
The ability to call PL/SQL functions in SQL has been around since Release 2.1, but in many ways (at
least until Oracle8) it can still be considered "bleeding edge" technology. Why?
● You must manually apply RESTRICT_REFERENCES pragmas to all of your code and you
have to figure out where all those pragmas need to go. This process is described in a
subsection below.
● Functions execute outside of the read consistency model of the Oracle database (!). This issue
is also explored below in a subsection below.
● The overhead of calling a function from SQL remains high. The exact price you pay to call a
function from within SQL (compared to, say, executing in-line SQL code) can be hard to pin
down. It varies from computer to computer and even by instance or by the function being
called; I have heard reports that range from an extra half-second to an astonishing additional
50 seconds (in that case, I suggested that they do some more analysis and debugging).
Whatever the specific amount of time, the delay can be noticeable and you need to factor it
into your design and test plans.
● Tuning mechanisms such as EXPLAIN PLAN do not take into account the SQL that may be
called inside functions called in your SQL statement. PL/SQL functions are ignored by the
EXPLAIN PLAN facility. This makes it very difficult to come up with a comprehensive
understanding of performance bottlenecks and tuning needs.
● So much Oracle technology, especially that found in built-in packages, is declared "off limits"
to functions in SQL. Just consider DBMS_OUTPUT. You can't use it in functions called in
SQL. But ideally you will want to use those same functions in SQL and PL/SQL. Another
issue may be that your standard debugging technique is to insert calls to a trace program at the
beginning of each of your functions and procedures. Chances are that the trace program relies
on DBMS_OUTPUT (or UTL_FILE or DBMS_PIPE or take your pick, they're all at least
until Oracle8 off limits). Sorry! You will not be able to use that function in SQL. So you
have to pull out some of the code from the function. As a result, you can end up with two
versions of your code: one for PL/SQL and one for SQL. That is one nasty scenario for
software developers.
Let's examine two of these issues in more detail.
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
17.7.1 Manual Application of Pragmas
You must manually apply RESTRICT_REFERENCES pragmas to all of your code and you have
to figure out where all those pragmas need to go. This process is often similar to a Sherlock Holmes
plot. You compile a package and get a pragma violation error. This can happen because your program
breaks a rule (like trying to change data) or because it calls other programs which break a rule. You
notice in this case that your function calls five or six other functions or procedures, so you must apply
pragmas to each of these. By doing so, you assert purity levels where none had been asserted before,
raising more errors and in some cases significant architectural issues.
For example, suppose that you suddenly have to apply a pragma to a procedure in package X and that
package has an initialization section; you must then also pragma-tize the initialization section. A
common practice in this section is to set up a PL/SQL table for in-memory manipulation of data. If
you use any PL/SQL table methods to do this initialization, your pragma will fail.
This can be a very frustrating exercise, at times leading to abandoning the effort to enable your
function for execution in SQL. In my experience, you will want to identify in advance (as much as
possible) those areas of your application which you will want to call in SQL. You will then strive to
keep this code very "clean" and focused, with limited entanglements with other packages, and with an
absolutely minimal use of built-in packaged functionality. Neither an easy nor a particularly desirable
task.
17.7.2 Read Consistency Model Complications
Yes, it is hard to believe, but quite true: unless you take special precautions, it is quite possible that
your SQL query will violate the read consistency model of the Oracle RDBMS, which has been
sacrosanct territory for years at Oracle. To understand this issue, consider the following query and the
function it calls:
SELECT name, total_sales (account_id)
FROM account
WHERE status = 'ACTIVE';
FUNCTION total_sales (id_in IN account.account_id%TYPE)
RETURN NUMBER
IS
CURSOR tot_cur
IS
SELECT SUM (sales) total
FROM orders
WHERE account_id = id_in
AND year = TO_NUMBER (TO_CHAR (SYSDATE, 'YYYY'));
tot_rec tot_cur%ROWTYPE;
BEGIN
OPEN tot_cur;
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
[...]... triggers from Oracle7 ); ways of using PL/SQL objects with the Oracle Call Interface (OCI) for C or C++; and some of the physical storage considerations of objects 18.1 Introduction to Oracle8 Objects When a mainstream vendor like Oracle Corporation ventures into new technology waters, it is virtually certain that the change will be evolutionary rather than revolutionary True to form, Oracle8 's relational... include constants, exceptions, cursors, or datatypes Table 18.1 compares the new object features with features of tables and packages Table 18.1: Comparing Oracle8 Objects to Earlier Oracle Features Characteristic Oracle7 Table Oracle7 Package Oracle8 Object Stores data Yes Temporary only; package variables exist for duration of session Object instance data may be persistent (stored in tables) or transient... within Oracle Previous: 17.8 Examples of Embedded PL/SQL 17.8 Examples of Embedded PL/SQL Oracle PL/SQL Programming, 2nd Edition Book Index Next: 18 Object Types 18 Object Types The Oracle Library Navigation Copyright (c) 2000 O'Reilly & Associates All rights reserved Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Previous: V New PL/ SQL8 Features Chapter 18 Next: 18.2 Oracle. .. maybe your response is "objects, schmobjects, who needs `em?", or maybe objects haven't even been on your radar screen because you're living with Oracle, and Oracle is, well, a relational database, with only rows and columns That used to be true Now with Oracle' s objects option, the database can contain not only rows and columns, but also complex data structures which encapsulate both data and behavior... terminology before plunging into the details of the Oracle objects option First we'll look at the objects option in the context of the relational features of the Oracle server, and give some examples of places where objects can be used To put the subject in the broader technology context, we'll also step back to look at what it means to be object-oriented, and how Oracle fulfills the object motif Next, we'll... Features Part V of this book contains the main discussion of the new features of Oracle8 that are relevant to PL/SQL q q q q Chapter 18, Object Types, describes the Oracle "object-relational model" and how the object features work Chapter 19, Nested Tables and VARRAYs, examines the two types of "collection" structures introduced in Oracle8 Chapter 20, Object Views, describes object views, which let you use... will be evolutionary rather than revolutionary True to form, Oracle8 's relational capabilities are still the mainstay of Oracle Corporation's flagship database server, and these capabilities satisfy the need for compatibility with older Oracle versions But with the objects option, Oracle8 allows programmers to use a new set of datatypes and models drawn from object programming languages, allowing persistent... least they don't use alien punctuation!) 18.1.1 Terminology The first big hurdle to cross is the nomenclature; object technology in general, and Oracle8 in particular, seem to litter us with terms that seem familiar but aren't For example, even prior to Oracle8 , Oracle did have objects that is, tables, indexes, packages, procedures, etc in fact, you can see them all in the USER_OBJECTS view Now we... USER_OBJECTS I'll call the database objects, and Oracle8 objects I'll call simply objects Rather than lob all the new terminology at you in eye-glazing detail, I'll introduce the most important terms first, and present the others as needed These terms are not strictly from the lexicon of objectoriented purists, but are defined in an Oracle context Object type An Oracle database construct, managed via Data... www.verypdf.com to remove this watermark other languages) and can be invoked as an Oracle "external procedure" (see Chapter 21, External Procedures) There is a special default method supplied by Oracle, a constructor, that initializes objects 18.1.2 Some Simple Examples To give you a better sense of how object technology works in Oracle, let's look at some specific code samples that use objects The following . will violate the read consistency model of the Oracle RDBMS, which has been
sacrosanct territory for years at Oracle. To understand this issue, consider the. that about almost every aspect of Oracle technology, especially the newer
additions to the stable. I hope that over time Oracle will make our lives easier