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

Oracle XSQL- P14 doc

20 148 0

Đ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

Định dạng
Số trang 20
Dung lượng 182,52 KB

Nội dung

The WHILE LOOP moves the EXIT condition to the top of the loop: SET SERVEROUTPUT ON DECLARE dummy_var NUMBER(2); BEGIN dummy_var:=1; WHILE dummy_var<=15 LOOP DBMS_OUTPUT.PUT_LINE(‘dummy_var: ‘||dummy_var); dummy_var:=dummy_var+1; END LOOP; END; The FOR LOOP is most convenient for this kind of loop. It handles the counting for you. You are also guaranteed that the FOR LOOP will exit—PL/SQL won’t let you assign to the counter while the loop is in progress. SET SERVEROUTPUT ON BEGIN FOR dummy_var IN 1 15 LOOP DBMS_OUTPUT.PUT_LINE(‘dummy_var: ‘||dummy_var); END LOOP; END; Sequential Control Structures The sequential control structures are the GOTO and the NULL statements. You shouldn’t use GOTO statements in your code, even if it is really complicated. Instead, you should try to simplify your code and probably write some subroutines. If you really, really have to write a GOTO, here is how you do it: statement statement GOTO goto_target statement statement statement <<goto_target>> statement you want to go to The NULL statement does nothing. It is convenient as a placeholder and generally should be removed after development. During development, you might need it 240 Chapter 9 because of PL/SQL’s requirement that each block have at least one valid statement. If you have constructed a complicated series of IF-THEN-ELSE statements, you might find that you don’t want a particular block to do anything. However, your PL/SQL won’t execute without a valid statement. Instead of disturbing the overall structure of your code, you can just throw in a NULL statement. In this way, you meet both goals— The code will run, and the problem block won’t do anything. Here’s an example: IF a < b THEN NULL; END IF; Cursors Earlier in this chapter, in the section entitled “Declaring Variables,” you got your first glimpse of cursors. Now you get to see them in action. A cursor allows you to pro- grammatically move through the results of a SQL query. Here is an example: SET SERVEROUTPUT ON DECLARE CURSOR emp_cursor IS SELECT * FROM emp; emp_rec emp%ROWTYPE; BEGIN FOR emp_rec IN emp_cursor LOOP DBMS_OUTPUT.PUT_LINE(emp_rec.ename); END LOOP; END; This code will print each employee’s name. Of course, you can do anything you want with the data that is captured in the emp_rec variable. Before going any further, you should know the syntax of the FOR IN LOOP. Notice that you can define the cur- sor in the LOOP with the SELECT statement. It’s generally better to define it as a vari- able, though, so that your code is more readable. FOR {scalar_variable . . . | record } IN {cursor_name | (SELECT_statement) } LOOP {statement;} [statement; . . .] END LOOP; PL/SQL 241 You are also not restricted to using the FOR IN LOOP as shown here. You can open and close the cursor explicitly and fetch the records. Here is some sample code that does the same thing using this methodology: SET SERVEROUTPUT ON DECLARE CURSOR emp_cursor IS SELECT * FROM emp; emp_rec emp%ROWTYPE; BEGIN OPEN emp_cursor; LOOP FETCH emp_cursor INTO emp_rec; EXIT WHEN emp_cursor%NOTFOUND; DBMS_OUTPUT.PUT_LINE(emp_rec.ename); END LOOP; CLOSE emp_cursor; END; This introduces three new keywords: (1) OPEN, (2) CLOSE, and (3) FETCH. OPEN and CLOSE are both simple—you just follow them with a cursor name. FETCH is only slightly more complex. You can follow it with one or more variables instead of a record. Notice how the EXIT condition works in this case. There is a cursor attribute, NOT- FOUND, that evaluates as true when the cursor returns some data. There are a total of four attributes for cursors, which are described Table 9.5. You can use cursors with UPDATE and DELETE statements, also. By specifying CUR- RENT OF in the where clause, the update statement will work against the last row fetched from the specified cursor. This assumes that there is nothing else in the WHERE clause that will cause the update to skip that particular row. The following sample code, which works against a copy of emp called dummy_emp, shows how this works. The same syntax works for a DELETE statement. SET SERVEROUTPUT ON DECLARE CURSOR emp_cursor IS SELECT * FROM dummy_emp FOR UPDATE OF sal; emp_rec dummy_emp%ROWTYPE; BEGIN OPEN emp_cursor; LOOP FETCH emp_cursor INTO emp_rec; EXIT WHEN emp_cursor%NOTFOUND; UPDATE dummy_emp SET sal=emp_rec.sal+100 WHERE CURRENT OF emp_cursor; END LOOP; CLOSE emp_cursor; END; 242 Chapter 9 Table 9.5 Cursor Attributes ATTRIBUTE DESCRIPTION %FOUND True if the previous fetch returned a row. %NOTFOUND True if the previous fetch didn’t return a row. %ISOPEN True if the cursor is open. %ROWCOUNT Number of rows returned by the cursor so far. You can also return a cursor from a function. XSQL has special support for this with the REF-CURSOR-FUNCTION action. The idea is that instead of returning just a single point of data, you return an indeterminate number of rows—just like a SELECT state- ment. What is different is that you can use all of the power of PL/SQL to determine the data that you wish to return. Here is a simple example that allows you to control whether to get the salaries that are greater than or less than the given value: CREATE OR REPLACE PACKAGE ref_cursor_example IS TYPE emp_sal_cursor_type IS REF CURSOR; FUNCTION return_cursor(comp_sal NUMBER,op VARCHAR2) RETURN emp_sal_cursor_type; END; CREATE OR REPLACE PACKAGE BODY ref_cursor_example IS FUNCTION return_cursor(comp_sal NUMBER, op VARCHAR2) RETURN emp_sal_cursor_type IS emp_sal_cursor emp_sal_cursor_type; BEGIN IF op=’greater’ THEN OPEN emp_sal_cursor FOR SELECT * FROM emp WHERE sal>comp_sal; ELSE OPEN emp_sal_cursor FOR SELECT * FROM emp WHERE sal<=comp_sal; END IF; RETURN emp_sal_cursor; END; END; You can access this function directly using the XSQL REF-CURSOR-FUNCTION action: <?xml version=”1.0”?> <page connection=”demo” xmlns:xsql=”urn:oracle-xsql”> <xsql:ref-cursor-function> ref_cursor_example.return_cursor(1200,’greater’) </xsql:ref-cursor-function> </page> PL/SQL 243 Packages A package is a way to group your PL/SQL types, items, procedures, and functions together. Type definitions, such as records and cursors, can be defined once for all of your subroutines. You can declare variables at a package level that all of the procedures and functions can share. However, all procedures and functions share the exact same copy of the variables—if it is changed by a subroutine, all subroutines will see the same change (i.e., they aren’t like the instance variables of object-oriented languages). As you saw in the hello_pkg example earlier, a package definition has two parts: (1) a package specification and (2) a package body. If you want a subroutine, type, or variable to be publicly available beyond your package, you must include it in the pack- age specification. Private items that are only available to the package code should only be defined in the package body. The following specification extends our earlier example to include a public variable, pub_var. CREATE OR REPLACE PACKAGE hello_pkg AS pub_var NUMBER(6):=0; FUNCTION hello_plsql (param NUMBER) RETURN VARCHAR2; END hello_pkg; This package body includes a private variable, priv_var, and a private procedure, priv_proc. CREATE OR REPLACE PACKAGE BODY hello_pkg AS package body header priv_var NUMBER(6); PROCEDURE priv_proc IS BEGIN priv_var:=priv_var+1; END; FUNCTION hello_plsql (param NUMBER) RETURN VARCHAR2 IS hello_str VARCHAR2(20); sal_val NUMBER(7,2); BEGIN priv_proc; pub_var:=pub_var+1; other function code END; END hello_pkg; Because package level variables are shared by all of the executing subroutines, their usefulness is limited. However, it is quite useful to define types, such as records and 244 Chapter 9 cursors, once for a set of different subroutines and to group related subroutines together. Though you can create functions and procedures as separate entities, it is advisable to consider creating a package instead. Procedures and Functions You’ve now seen the three ways to write PL/SQL code for execution: (1) functions, (2) anonymous blocks, and (3) procedures. This section looks specifically at subprograms: procedures and functions. There is only one key difference between procedures and functions: A procedure doesn’t return a value, whereas a function does. (Thus, a pro- cedure is like a void method in Java or a void function in C++.) Procedures and func- tions are alike except for this difference. In our examples thus far, you have created procedures and functions as part of pack- ages. You can also create subprograms as stand-alone objects with the CREATE OR REPLACE PROCEDURE and CREATE OR REPLACE FUNCTION statements. Here are examples creating stand-alone subprograms: CREATE OR REPLACE FUNCTION simple_func (param NUMBER) RETURN VARCHAR2 IS hello_str VARCHAR2(20); func_var NUMBER(7,2); BEGIN func_var:=param+1; RETURN ‘hello ‘|| func_var; END; CREATE OR REPLACE PROCEDURE priv_proc (param NUMBER) IS proc_var NUMBER(7,2); BEGIN proc_var:=param+1; DBMS_OUTPUT.PUT_LINE(‘hello’||proc_var); END; The declaration section is implicit—it’s between the IS and the BEGIN keywords. The BEGIN and END keywords contain the execution block, which you learned about previously, and can optionally have an EXCEPTION block. To fill out a basic under- standing of PL/SQL subprograms, you need to understand how parameters are passed to PL/SQL subprograms. Parameters can be passed as IN, OUT, IN OUT, and NO COPY. These options are outlined in Table 9.6. Among other things, they affect whether a parameter is passed by reference or by value. When passing by value, a copy is made. Changes to the parameter won’t be seen outside the subprogram. When pass- ing by reference, a reference to the actual parameter is passed. If you modify the parameter inside your subprogram, it will be modified in the code that called your subprogram. PL/SQL 245 Table 9.6 Parameter Options OPTION DESCRIPTION IN A parameter is an input parameter. Inside the subprogram the parameter acts as a constant. It is always passed by reference. OUT A parameter is an output parameter. Inside the subprogram the parameter acts as a variable. Changes made to the variable inside the subprogram will be seen by the code calling the subprogram. By default, it is passed by value. Not allowed directly with XSQL. IN OUT A parameter is both an input and output parameter. It acts as an initialized value. By default it is passed by value. Not allowed directly with XSQL. NOCOPY A compiler hint used to make PL/SQL more efficient. When used in conjunction with OUT and IN OUT, it tells PL/SQL that the parameter may be passed by reference instead of by value. It has no effect when used with IN. In certain cases, PL/SQL will pass by value in spite of the NOCOPY hint. You can’t call procedures and functions with OUT parameters with XSQL directly when there is no place to which you can return the variable. For instance, you can call such subprograms from inside an xsql:dml anonymous block, but not as a single procedure or function call in xsql:dummy or xsql:include-owa. If you have a pro- cedure or function that you need to use that has OUT parameters, the workaround is to write a wrapper function or procedure. If you need data that is returned via an OUT parameter, you can write a function that returns the value, or use xsql:include -owa to write it back to the page. If you don’t need the data returned by the OUT parameter, you can simply disregard it in your wrapper function. In general, you’ll want to write wrapper functions, unless you are using xsql:include-owa. By default, parameters are passed as IN parameters. The following example shows how to specify each type: CREATE OR REPLACE PROCEDURE priv_proc (defaultInParam NUMBER, inParam IN NUMBER, inOutParam IN OUT NUMBER, outParam OUT NUMBER, noCopyParam IN OUT NOCOPY NUMBER) IS declaration BEGIN execution END; 246 Chapter 9 There is one point left to be covered regarding parameters and PL/SQL. You will occasionally see a subprogram called as follows: update_emp(emp_number=>7790,sal=>5000,name=>’EDWARDS’); This is named notation as opposed to positional notation. Positional notation might look like this instead, assuming that the order of parameters in the update_emp defi- nition is name, emp_number, and sal. update_emp(‘EDWARDS’,7790,5000); Positional notation is typical of many popular programming languages. However, named notation is self-documenting, easier to read, and easier to get right. You can more easily avoid the classic problem of interchanging variables of the same type. For instance, if 7,790 and 5,000 were interchanged in our example, the wrong employee might get an unexpected raise! Exceptions PL/SQL uses exception handling to help you deal with unexpected conditions. Excep- tions don’t bugproof your code, but they do make it easier to make your code bullet- proof. Instead of having to use extensive logic to make sure that your code doesn’t crash, you can use exception handlers to define what should happen if something does go wrong. PL/SQL comes with several built-in exceptions, which are tied to Oracle error codes. You can also define your own exceptions and raise exceptions from within your execution block. This section covers all of these aspects of exceptions. First, a more extensive example using exceptions is needed. So far, you’ve had exception sections that only handle one exception. This example shows how you can use the exception section to handle multiple exceptions. CREATE OR REPLACE PROCEDURE print_high_sal(sal_var IN OUT emp.sal%TYPE) IS BEGIN SELECT sal INTO sal_var FROM emp WHERE sal>sal_var; DBMS_OUTPUT.PUT_LINE(‘sal_var’||sal_var); EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE(‘no data’); WHEN TOO_MANY_ROWS THEN DBMS_OUTPUT.PUT_LINE(‘too many rows’); WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(‘unknown error’); END; There are several things that can go wrong. First, our SELECT statement might not return any rows. If that happens, the NO_DATA_FOUND exception is raised and han- dled. The opposite might occur, in which more than one row is returned. In that case, the TOO_MANY_ROWS exception handler will execute. If anything else goes wrong, the OTHERS handler kicks in. PL/SQL 247 When an exception is raised, execution immediately either switches to the applica- ble exception handler, or PL/SQL exits with an error message. If you are writing a function, you should return a value in all of your exception handlers. Using the OTHERS exception handler always guarantees that your code will exit gracefully. Except the OTHERS handler, all of the built-in exception handlers are tied to an Ora- cle error code. Table 9.7 lists all of them. In addition to these exceptions, you can declare your own. You do this in the DECLARE section as follows: DECLARE obsolete_exception EXCEPTION; PRAGMA EXCEPTION_INIT (obsolete_exception,-3007); my_exception EXCEPTION; BEGIN code EXCEPTION WHEN obsolete_exception THEN DBMS_OUTPUT.PUT_LINE(‘obsolete feature used’); WHEN my_exeception THEN DBMS_OUTPUT.PUT_LINE(‘my_exception was raised’); END; The exception obsolete_exception is tied to ORA-03007, “obsolete feature.” (The actual error number is almost always the negative of the number in the name of the error.) If the ORA-03007 error occurs, then the handler will print out the message. The story is different for my_exception. Because my_exception isn’t tied to an error message, it has to be raised explicitly. You do this with the raise keyword as fol- lows. Typically, you would raise an exception from within a control structure because something didn’t go as planned: BEGIN statement statement RAISE my_exception; statement statement EXCEPTION WHEN my_exeception THEN DBMS_OUTPUT.PUT_LINE(‘my_exception was raised’); END; Triggers If you want to execute a procedure or function, you have to call it explicitly. For instance, you called the hello_pkg.hello_plsql function by selecting it from the dual table. Triggers, on the other hand, respond to events. Triggers are tied to inserts, updates, and deletions of particular tables. The syntax for creating triggers is as follows: 248 Chapter 9 Table 9.7 Built-in Exceptions NAME DESCRIPTION ACCESS_INTO_NULL An assignment was attempted to an attribute of an uninitialized object. CASE_NOT_FOUND No cases were met in a CASE statement that didn’t have a ELSE clause. COLLECTION_IS_NULL A collection method other than EXISTS was called on a collection that hasn’t been initialized. CURSOR_ALREADY_OPEN OPEN was called on a cursor that is already open. DUP_VAL_ON_INDEX A unique column constraint was violated. INVALID_CURSOR An illegal cursor operation was attempted. INVALID_NUMBER An invalid string-to-number conversion was attempted in a SQL statement. NO_DATA_FOUND A SELECT INTO statement returns no rows. PROGRAM_ERROR Internal PL/SQL error. ROWTYPE_MISMATCH The host cursor variable and PL/SQL cursor variable involved in an assignment have incompatible return types. For example, when an open host cursor variable is passed to a stored subprogram, the return types of the actual and formal parameters must be compatible. SELF_IS_NULL Access of a member method of an uninitialized object was attempted. STORAGE_ERROR A memory error occurred. SUBSCRIPT_BEYOND_COUNT An attempt was made to access a collection with a number larger than the size of the collection. SUBSCRIPT_OUTSIDE_LIMIT An attempt was made to access a collection with a number outside the legal range. SYS_INVALID_ROWID A ROWID conversion failed because the string doesn’t represent a valid ROWID. TIMEOUT_ON_RESOURCE A time-out occurs while Oracle is waiting for a resource. TOO_MANY_ROWS A SELECT INTO statement returns more than one row. VALUE_ERROR An arithmetic, conversion, truncation, or size- constraint error occurred. ZERO_DIVIDE An attempt was made to divide a number by zero. PL/SQL 249 [...]... other documents in the set Table 10.1 lists the results Using Oracle Text Table 10.1 Scoring Results DOC_ NAME TEXT_SCORE allow doc 9 HTML doc 4 XML doc 4 As you may have guessed, you could have gotten only the allow doc if you had said contains(text,’language’,1)>4 You can also establish a threshold inside of the search expression itself Here is an example that will select only allow doc and XML doc. .. allows you to make beautiful documents’); 253 254 Chapter 10 ■ ■ INSERT INTO docs_table (id ,doc_ name,text) VALUES (2,’About XML’,’XML is a language where you are allowed to make beautiful languages’); ■ ■ INSERT INTO docs_table (id ,doc_ name,text) VALUES (3,’allow doc ,’An allowance was made so that beautiful presents can be given to the language department’); ■ ■ ALTER INDEX docs_index REBUILD; ■ ■ COMMIT;... because allowed and allows have the same root as allowing SELECT doc_ name,score(1) FROM docs_table WHERE contains(text,’$allowing’,1)>0 ORDER BY score(1) DESC Searching within XML Documents Oracle Text can also be used to perform searches within sections of a document stored in the database This includes HTML documents and other non-XML documents You can also do searches on terms within the same sentence... in the Oracle Text Reference” at Oracle s techweb Web site DROP INDEX docs_index; EXEC CTX_DDL.CREATE_SECTION_GROUP(‘sample_group’,’PATH_SECTION_GROUP’); CREATE INDEX docs_index ON docs_table(text) INDEXTYPE IS ctxsys.context PARAMETERS(‘section group sample_group’); Now that you have created the index, you are ready to start searching The following query will return both documents: SELECT id ,doc_ name... French, you can search documents based on what they are about Oracle classifies documents into themes such as politics You can search on politics and documents that don’t contain the word “politics” but are about politics will be returned Searching on other formatted documents In our examples, our documents were simple text or XML You can also insert and query more complex formatted documents (e.g., Microsoft... has an indexed column Oracle Text will work against any of the following data types: VARCHAR2, CLOB, BLOB, CHAR, BFILE, and XMLType For the lessons here, you’ll use a simple table with a VARCHAR2 column containing our small documents Here’s what you do: ■ ■ CREATE TABLE docs_table (id number primary key, doc_ name VARCHAR2(10),text VARCHAR2(2000)); ■ ■ INSERT INTO docs_table (id ,doc_ name,text) VALUES... SELECT id ,doc_ name FROM docs_table WHERE contains(text,’people INPATH (/article/body)’)>0; 257 258 Chapter 10 You can use its companion, HASPATH, to only return articles that have a certain path For instance, only one of our documents has the element reference Here’s how you would use HASPATH so that only those documents having a reference element will be returned: SELECT id ,doc_ name FROM docs_table... those unstructured searches to particular XML elements within the document Some assembly is required As a first step, let’s create a couple of new XML documents and insert them into the table These statements should do the trick: INSERT INTO docs_table (id ,doc_ name,text) VALUES (3, doc2 ’, ‘ networking Using Oracle Text Networking Basics People didn’t... ’ ); INSERT INTO docs_table (id ,doc_ name,text) VALUES (4, doc3 ’,’ software Mythical Man Month, Dr Fred Brooks Brook’’s Law Putting more people on a late software project makes it later. ’ ); COMMIT; Next, you need to re-create the index so that Oracle is able to search on the XML documents You’ll notice... use both Oracle SQL and its procedural counterpart, PL/SQL You should have a solid understanding of how you use these technologies with XSQL In Chapters 10 (“Using Oracle Text”) and 11 (“Retrieving XML”), you’ll see how to use Oracle to do specialized text searching and retrieving and managing XML Then, you’ll complete your base knowledge by learning XSLT 251 CHAPTER 10 Using Oracle Text Oracle Text . con- taining our small documents. Here’s what you do: ■■ CREATE TABLE docs_table (id number primary key, doc_ name VARCHAR2(10),text VARCHAR2(2000)); ■■ INSERT INTO docs_table (id ,doc_ name,text) VALUES. term or terms than the other documents in the set. Table 10.1 lists the results. 254 Chapter 10 Table 10.1 Scoring Results DOC_ NAME TEXT_SCORE allow doc 9 HTML doc 4 XML doc 4 As you may have guessed,. languages’); ■■ INSERT INTO docs_table (id ,doc_ name,text) VALUES (3,’allow doc ,’An allowance was made so that beautiful presents can be given to the language department’); ■■ ALTER INDEX docs_index REBUILD; ■■ COMMIT; Simple

Ngày đăng: 03/07/2014, 08:20

TỪ KHÓA LIÊN QUAN

w