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

Tài liệu Oracle PLSQL Language- P13 ppt

50 315 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 50
Dung lượng 168,44 KB

Nội dung

10.5.3 Nonsequential Use of PL/SQL Table Of course, the idea of using a minimum and maximum row assumes that the rows in the table are used sequentially. That is, you fill row one, then row two, etc. This is a perfectly reasonable way to fill a table's rows; to do this you absolutely must know the value of the row last filled. You are not, however, required to fill rows in this way. You can place a value in any row of the table you wish, regardless of the primary key value of the last row you filled. The following example illustrates filling a PL/SQL table's rows randomly rather than sequentially: DECLARE TYPE countdown_tests_tabtype IS TABLE OF VARCHAR2(20) INDEX BY BINARY_INTEGER; countdown_test_list countdown_tests_tabtype; BEGIN countdown_test_list (1) := 'All systems go'; countdown_test_list (43) := 'Internal pressure'; countdown_test_list (255) := 'Engine inflow'; END; In this situation, the minimum and maximum values do not have much significance. The ability to randomly place values in a table can come in very handy when the primary key value for the table's row is actually not sequentially derived, but is instead based on data in your application. This use of "intelligent" primary key values is explored in more detail in Section 10.9.2, "Data-Smart Row Numbers in PL/SQL Tables" later in this chapter. 10.5.4 Passing PL/SQL Tables as Parameters You can also pass a PL/SQL table as a parameter in a procedure or function; with this approach you can, in a single call, pass all the values in a table into the module. In the following package specification I define two modules that pass PL/SQL tables as parameters. The send_promos procedure sends a promotional mailing to all the companies in my table. The companies_overdue function returns a table filled with the names of companies that have overdue bills. PACKAGE company_pkg IS TYPE primary_keys_tabtype IS TABLE OF company. company_id%TYPE NOT NULL INDEX BY BINARY_INTEGER; company_keys_tab primary_keys_tabtype; emp_keys_tab primary_keys_tabtype; Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. /* Table type and table for company names */ TYPE company_names_tabtype IS TABLE OF company.name% TYPE INDEX BY BINARY_INTEGER; company_names_tab company_names_tabtype; /* Parameter is a table of company primary keys */ PROCEDURE send_promos (company_table_in IN primary_keys_tabtype); /* Function returns a table of company names */ FUNCTION companies_overdue (overdue_date_in IN DATE) RETURN company_names_tabtype; /* Returns company ID for name. */ FUNCTION id (name in IN company.name%TYPE) RETURN company.company id%TYPE END company_pkg; Now that I have a package containing both the table type and the programs referencing those types, I can call these programs. The only tricky part to remember here is that you must declare a PL/SQL table based on the type before you can use any of the programs. Here is an example of returning a PL/ SQL table as a function's return value: CREATE OR REPLACE PROCEDURE send_promos_for_overdue_companies (date_in IN DATE := SYSDATE) IS v_row PLS_INTEGER; /* Declare a PL/SQL table based on the packaged type. */ cnames company_pkg.company_names_tabtype; BEGIN cnames := company_pkg.companies_overdue (date_in); /* || In PL/SQL 2.3 I can use navigation methods to traverse. || Notice that I do not assume that rows are filled sequentially. */ v_row := cnames.FIRST; LOOP EXIT WHEN v_row IS NULL; Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. DBMS_OUTPUT.PUT_LINE (cnames(v_row)); v_row := cnames.NEXT (v_row); END LOOP; END; / Notice that I could also have avoided declaring my own PL/SQL table, cnames, by using the predefined table in the package: company_pkg.company_names_tab := company_pkg.companies_overdue (date_in); If I had taken this approach, however, any rows already defined in this "global" table would have been erased. Here is an example of calling a procedure, passing a PL/SQL table as an argument in the parameter list: DECLARE v_row PLS_INTEGER; /* Table of primary keys for company */ company_ids company_pkg.primary_keys_tabtype; BEGIN /* Populate the table with names of overdue companies. */ company_pkg.company_names_tab := company_pkg.companies_overdue (date_in); /* For each company name, look up the ID and pass it to the || PL/SQL table of company IDs. */ v_row := company_pkg.company_names_tab.FIRST; LOOP EXIT WHEN v_row IS NULL; company_ids (NVL (company_ids.LAST, 0) + 1) := company_pkg.id(company_pkg.company_name_tab (v_row)); v_row := company_pkg.company_names_tab.NEXT (v_row); END LOOP; /* Now send out promotional flyers to those companies. */ company_pkg.send_promos (company_ids); Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. /* Delete all the rows from the company names table. */ company_pkg.company_names_tab.DELETE; END company_pkg; Previous: 10.4 Declaring a PL/SQL Table Oracle PL/SQL Programming, 2nd Edition Next: 10.6 Filling the Rows of a PL/SQL Table 10.4 Declaring a PL/SQL Table Book Index 10.6 Filling the Rows of a PL/ SQL Table 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: 10.5 Referencing and Modifying PL/SQL Table Rows Chapter 10 PL/SQL Tables Next: 10.7 Clearing the PL/ SQL Table 10.6 Filling the Rows of a PL/SQL Table You can assign values to rows of a table in several ways: ● Direct assignment ● Iterative assignment ● Aggregate assignment These methods are described in the following sections. 10.6.1 Direct Assignment As shown in previous examples, you can simply assign a value to a row with the assignment operator: countdown_test_list (43) := 'Internal pressure'; company_names_table (last_name_row) := 'Johnstone Clingers'; Direct assignment makes sense when you need to make a change to a specific row. But what do you use when you want to fill a whole set of rows, for example, unloading a whole cursor-full of information from a database table? Here, iterative assignment may be more appropriate. 10.6.2 Iterative Assignment In order to fill up multiple rows of a table, I recommend taking advantage of a PL/SQL loop. Within the loop you will still perform direct assignments to set the values of each row, but the primary key value will be set by the loop rather than hardcoded into the assignment itself. In the following example, I use a WHILE loop to fill and then display a PL/SQL date table with the next set of business days, as specified by the ndays_in parameter: Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. /* Filename on companion disk: bizdays.sp */ CREATE OR REPLACE PROCEDURE show_bizdays (start_date_in IN DATE := SYSDATE, ndays_in IN INTEGER := 30) IS TYPE date_tabtype IS TABLE OF DATE INDEX BY BINARY_INTEGER; bizdays date_tabtype; /* The row in the table containing the nth_day */ nth_day BINARY_INTEGER := 1; v_date DATE := start_date_in; BEGIN /* Loop through the calendar until enough biz days are found */ WHILE nth_day <= ndays_in LOOP /* If the day is not on the weekend, add to the table. */ IF TO_CHAR (v_date, 'DY') NOT IN ('SAT', 'SUN') THEN bizdays (nth_day) := v_date; DBMS_OUTPUT.PUT_LINE (v_date); nth_day := nth_day + 1; END IF; v_date := v_date + 1; END LOOP; END show_bizdays; / As you can see from this example, using the WHILE loop produces a neat, sequential load of the PL/ SQL table. 10.6.3 Aggregate Assignment Just as you can assign one entire record to another record of the same type and structure, you can perform aggregate assignments with tables as well. In order to transfer the values of one table to another, the datatype of the two tables must be compatible. Beyond that you simply use the assignment operator (:=) to transfer the values of one table to the other. The following example contains an example of an aggregate table assignment: DECLARE TYPE name_table IS TABLE OF VARCHAR2(100) INDEX BY BINARY_INTEGER; old_names name_table; Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. new_names name_table; BEGIN /* Assign values to old_names table */ old_names(1) := 'Smith'; old_names(2) := 'Harrison'; /* Assign values to new_names table */ new_names(111) := 'Hanrahan'; new_names(342) := 'Blimey'; /* Transfer values from new to old */ old_names := new_names; /* This assignment will raise NO_DATA_FOUND */ DBMS_OUTPUT.PUT_LINE (old_names (1)); END; A table-level assignment completely replaces the previously defined rows in the table. In the preceding example, rows 1 and 2 in old_names are defined before the last, aggregate assignment. After the assignment, only rows 111 and 342 in the old_names table have values. Previous: 10.5 Referencing and Modifying PL/SQL Table Rows Oracle PL/SQL Programming, 2nd Edition Next: 10.7 Clearing the PL/ SQL Table 10.5 Referencing and Modifying PL/SQL Table Rows Book Index 10.7 Clearing the PL/SQL Table 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: 10.6 Filling the Rows of a PL/SQL Table Chapter 10 PL/SQL Tables Next: 10.8 PL/SQL Table Enhancements in PL/SQL Release 2.3 10.7 Clearing the PL/SQL Table What happens when you are done with a PL/SQL table and want to remove it from memory? If a PL/ SQL table is like a table, we should be able to DELETE the rows of that table or DROP it entirely, right? It's a nice idea, but you can't perform a SQL DELETE statement on a PL/SQL table because it is not stored in the database. You also cannot DROP a PL/SQL table. You can set a single row to NULL with the following kind of assignment: company_names_table (num_rows) := NULL; But this assignment doesn't actually remove the row or make it undefined; it just sets the value of the row to NULL. The only way to actually empty a PL/SQL table of all rows is to perform an aggregate assignment with a table that is empty a table, that is, with no rows defined. With this approach, for every PL/SQL table you want to be able to empty, you declare a parallel, empty table of the same table type. When you are finished working with your table, simply assign the empty table to the actual table. This will unassign all the rows you have used. The following example demonstrates this technique: DECLARE TYPE company_names_tabtype IS TABLE OF company.name% TYPE INDEX BY BINARY_INTEGER; company_names_tab company_names_tabtype; /* Here is the empty table declaration */ empty_company_names_tab company_names_tabtype; BEGIN set values in company names table Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. /* The closest you can come to "dropping" a PL/SQL table */ company_names_tab := empty_company_names_tab; END; NOTE: PL/SQL Release 2.3 offers a DELETE operator so that you can delete all or some rows of a PL/SQL table. Previous: 10.6 Filling the Rows of a PL/SQL Table Oracle PL/SQL Programming, 2nd Edition Next: 10.8 PL/SQL Table Enhancements in PL/SQL Release 2.3 10.6 Filling the Rows of a PL/ SQL Table Book Index 10.8 PL/SQL Table Enhancements in PL/SQL Release 2.3 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: 10.7 Clearing the PL/SQL Table Chapter 10 PL/SQL Tables Next: 10.9 Working with PL/SQL Tables 10.8 PL/SQL Table Enhancements in PL/SQL Release 2.3 PL/SQL Release 2.3 offers significantly enhanced functionality for PL/SQL tables. These new features include: ● Records supported as elements of PL/SQL tables. Prior to Release 2.3, the element or single column of the PL/SQL table could only be a scalar datatype, such as VARCHAR2 or BOOLEAN or DATE. Release 2.3 allows you to define table types whose element datatype is defined with the %ROWTYPE declaration attribute or is a named RECORD type. ● New operations on PL/SQL tables. PL/SQL Release 2.3 offers a set of new built-in functions and procedures which return information about, or modify the contents of, a PL/SQL table. These operations are shown in Table 10.1. These new features allow you to use PL/SQL tables for a wider range of applications and also manipulate the data in tables in a more natural and efficient manner. You can now create local PL/ SQL data structures which mimic precisely the structure of a table stored in the database. You do not have to create separate tables and manage them in parallel to emulate the multiple-column SQL table structure. You can use the built-ins to obtain PL/SQL table information that previously was unavailable. For example, you can use the COUNT function to determine the number of elements defined in a table. You no longer have to keep track of that number yourself. Table 10.1: PL/SQL Release 2.3 Built-in Functions and Procedures for Tables Operator Description COUNT Returns the number of elements currently contained in the PL/SQL table. DELETE Deletes one or more elements from the PL/SQL table. Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. [...]... NULL if there aren't any elements defined before the specified row Previous: 10.7 Clearing the PL/SQL Table 10.7 Clearing the PL/SQL Table Oracle PL/SQL Programming, 2nd Edition Book Index Next: 10.9 Working with PL/SQL Tables 10.9 Working with PL/SQL Tables The Oracle Library Navigation Copyright (c) 2000 O'Reilly & Associates All rights reserved Please purchase PDF Split-Merge on www.verypdf.com to... TRUE if the 15th row of the company_tab PL/SQL table is defined: Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark company_tab.EXISTS(15) By using the member-method syntax, Oracle is able to distinguish the PL/SQL table functions such as EXISTS and DELETE from the SQL operations of the same name (which never appear with dotqualified notation) The following sections describe... your application In other words, it can be "data-smart." Suppose you want to use a PL/SQL table to store the text of messages associated with numeric error codes These error codes are patterned after Oracle error codes, with ranges of values set aside for different aspects of the application: 1000-1999 for employee-related errors, 5000-5999 for companyrelated errors, etc When a user action generates... might be sparsely filled; you might know the starting row (lowest value) and the ending row (maximum value), but not really know which of the rows between those end points are defined A table with the Oracle error codes would have all of these characteristics 10.9.3.1 A flexible display_table procedure It is possible to build a version of display_table which takes into account all of these variations... incremented as the procedure scans through the table The default is +1 If you know that every 15th row is defined, you can pass 15 and avoid the NO_DATA_FOUND exceptions If your rows are negative, as with Oracle error codes, specify -1 for the increment and the procedure will then scan backwards through the table This version of display_table shown in the following example displays both sequentially filled... display_table to view the contents of a sequentially filled table, the call to the procedure looks exactly the same as in the first version: display_table (customer_tab, num_customers); If I store the Oracle error codes in my table, then I can take advantage of all these different parameters to view only the errors dealing with the date functions (-01800 through -01899) with the following command: display_table... it (and test it) only once From then on, I simply substitute an actual table type 10.9.4 Building Traditional Arrays with PL/SQL Tables As I've mentioned, neither PL/SQL nor any other component of the Oracle product set supports true arrays You cannot, for example, declare a two-dimensional array which is manipulated with statements such as the following: company (2,3) := '100 Main St'; min_profits... from PL/SQL Release 1.1 The Version 1.1 layer cannot parse such references (see Appendix B, Calling Stored Procedures from PL/SQL Version 1.1) You can, however, call stored package functions from within Oracle Developer/2000 It is always better to hide the way you implement functionality, including variables names, data structures, and algorithms By not exposing the details (in this case, the names of... package level so it is available to all modules in the package without having to be passed as a parameter One final advantage is that you can call this array package (stored in the database) from within the Oracle Developer/2000 tools If the table were exposed, then the array could only be used in a PL/ SQL Version 2 environment Wow! When I decided to build it this way, I had no idea it would make this much . company_pkg.company_names_tab.DELETE; END company_pkg; Previous: 10.4 Declaring a PL/SQL Table Oracle PL/SQL Programming, 2nd Edition Next: 10.6 Filling the Rows of a PL/SQL. Declaring a PL/SQL Table Book Index 10.6 Filling the Rows of a PL/ SQL Table The Oracle Library Navigation Copyright (c) 2000 O'Reilly & Associates.

Ngày đăng: 21/01/2014, 08:20

TỪ KHÓA LIÊN QUAN