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

Tài liệu Oracle PL/SQL by Example- P9 pdf

50 417 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 264,27 KB

Nội dung

Consider partial output from the preceding example: Zip: 06820 Names(1): Scrittorale Names(2): Padel Names(3): Kiraly Zip: 06830 Names(1): Dennis Names(2): Meshaj Names(3): Dalvi Zip: 06880 Names(1): Miller Names(2): Cheevens Zip: 06903 Names(1): Segall Names(2): Annina Zip: 07003 Names(1): Wicelinski Names(2): Intal Zip: 07010 Names(1): Lopez Names(2): Mulroy Names(3): Velasco Names(4): Kelly Names(5): Tucker Names(6): Mithane PL/SQL procedure successfully completed. LAB 16.2 372 Lab 16.2 Exercises Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. LAB 16.3 Collections of Records LAB OBJECTIVE After completing this lab, you will be able to . Use collections of records In the previous lab you saw an example of a nested record in which one of the record fields was defined as an associative array. PL/SQL also lets you define a collection of records (such as an associative array whose element type is a cursor-based record, as shown in the following example). FOR EXAMPLE DECLARE CURSOR name_cur IS SELECT first_name, last_name FROM student WHERE ROWNUM <= 4; TYPE name_type IS TABLE OF name_cur%ROWTYPE INDEX BY BINARY_INTEGER; name_tab name_type; v_counter INTEGER := 0; BEGIN FOR name_rec IN name_cur LOOP v_counter := v_counter + 1; name_tab(v_counter).first_name := name_rec.first_name; name_tab(v_counter).last_name := name_rec.last_name; DBMS_OUTPUT.PUT_LINE('First Name('||v_counter||'): '|| name_tab(v_counter).first_name); DBMS_OUTPUT.PUT_LINE('Last Name('||v_counter||'): '|| name_tab(v_counter).last_name); END LOOP; END; LAB 16.3 373 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. ▼ In the declaration portion of this example, you define the name_cur cursor, which returns the first and last names of the first four students. Next, you define an associative array type whose element type is based on the cursor defined previously using the %ROWTYPE attribute. Then you define an associative array variable and the counter that is used later to reference individ- ual rows of the associative array. In the executable portion of the example, you populate the associative array and display its records on the screen. Consider the notation used in the example when referencing individual elements of the array: name_tab(v_counter).first_name and name_tab(v_counter).last_name Notice that to reference each row of the array, you use the counter variable, just like in all previ- ous examples. However, because each row of this table is a record, you must also reference indi- vidual fields of the underlying record. This example produces the following output: First Name(1): Fred Last Name(1): Crocitto First Name(2): J. Last Name(2): Landry First Name(3): Laetia Last Name(3): Enison First Name(4): Angel Last Name(4): Moskowitz PL/SQL procedure successfully completed. LAB 16.3 EXERCISES This section provides exercises and suggested answers, with discussion related to how those answers resulted. The most important thing to realize is whether your answer works. You should figure out the implications of the answers and what the effects are of any different answers you may come up with. 16.3.1 Use Collections of Records In this exercise, you learn more about collections of records. Complete the following tasks: A) Modify the script used earlier in this lab. Instead of using an associative array, use a nested table. ANSWER: The script should look similar to the following. Changes are shown in bold. ch16_4a.sql, version 1.0 SET SERVEROUTPUT ON DECLARE CURSOR name_cur IS SELECT first_name, last_name LAB 16.3 374 Lab 16.3 Exercises Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. FROM student WHERE ROWNUM <= 4; TYPE name_type IS TABLE OF name_cur%ROWTYPE; name_tab name_type := name_type(); v_counter INTEGER := 0; BEGIN FOR name_rec IN name_cur LOOP v_counter := v_counter + 1; name_tab.EXTEND; name_tab(v_counter).first_name := name_rec.first_name; name_tab(v_counter).last_name := name_rec.last_name; DBMS_OUTPUT.PUT_LINE('First Name('||v_counter||'): '|| name_tab(v_counter).first_name); DBMS_OUTPUT.PUT_LINE('Last Name('||v_counter||'): '|| name_tab(v_counter).last_name); END LOOP; END; In the preceding script, name_tab is declared as a nested table. As a result, at the time of its declaration, it is initialized. In other words, name_tab is empty but non-null. Furthermore, as soon as the name_tab table is initialized, its size must be increased before it can be populated with the next record. B) Modify the script used earlier in this lab. Instead of using an associative array, use a varray. ANSWER: The script should look similar to the following. Changes are shown in bold. ch16_4b.sql, version 2.0 SET SERVEROUTPUT ON DECLARE CURSOR name_cur IS SELECT first_name, last_name FROM student WHERE ROWNUM <= 4; TYPE name_type IS VARRAY(4) OF name_cur%ROWTYPE; name_tab name_type := name_type(); v_counter INTEGER := 0; BEGIN FOR name_rec IN name_cur LOOP v_counter := v_counter + 1; name_tab.EXTEND; name_tab(v_counter).first_name := name_rec.first_name; name_tab(v_counter).last_name := name_rec.last_name; DBMS_OUTPUT.PUT_LINE('First Name('||v_counter||'): '|| name_tab(v_counter).first_name); LAB 16.3 Lab 16.3 Exercises 375 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. DBMS_OUTPUT.PUT_LINE('Last Name('||v_counter||'): '|| name_tab(v_counter).last_name); END LOOP; END; In this version of the script, name_tab is declared as a varray with four elements. As in the previ- ous version, the collection is initialized and its size is incremented before it is populated with the new record. Both scripts, ch16_4a.sql and ch16_4b.sql, produce output identical to the original example: First Name(1): Fred Last Name(1): Crocitto First Name(2): J. Last Name(2): Landry First Name(3): Laetia Last Name(3): Enison First Name(4): Angel Last Name(4): Moskowitz PL/SQL procedure successfully completed. C) Modify the script used at the beginning of this lab. Instead of using a cursor-based record, use a user-defined record.The new record should have three fields: first_name, last_name, and enrollments.The last field will contain the total number of courses in which a student is currently enrolled. ANSWER: The script should look similar to the following. Changes are shown in bold. ch16_4c.sql, version 3.0 SET SERVEROUTPUT ON DECLARE CURSOR name_cur IS SELECT first_name, last_name, COUNT(*) total FROM student JOIN enrollment USING (student_id) GROUP BY first_name, last_name; TYPE student_rec_type IS RECORD (first_name VARCHAR2(15), last_name VARCHAR2(30), enrollments INTEGER); TYPE name_type IS TABLE OF student_rec_type INDEX BY BINARY_INTEGER; name_tab name_type; v_counter INTEGER := 0; BEGIN FOR name_rec IN name_cur LOOP v_counter := v_counter + 1; name_tab(v_counter).first_name := name_rec.first_name; name_tab(v_counter).last_name := name_rec.last_name; LAB 16.3 376 Lab 16.3 Exercises Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. name_tab(v_counter).enrollments := name_rec.total; IF v_counter <= 4 THEN DBMS_OUTPUT.PUT_LINE('First Name('||v_counter||'): '|| name_tab(v_counter).first_name); DBMS_OUTPUT.PUT_LINE('Last Name('||v_counter||'): '|| name_tab(v_counter).last_name); DBMS_OUTPUT.PUT_LINE('Enrollments('||v_counter||'): '|| name_tab(v_counter).enrollments); DBMS_OUTPUT.PUT_LINE (' '); END IF; END LOOP; END; In the declaration portion of the script, the cursor SELECT statement has been modified so that for each student it returns the total number of enrollments. Next, the user-defined record type, student_rec_type, is declared so that it can be used as the element type for the associative array type, name_type. In the executable portion of the script, the associative array, name_tab, is populated using the cursor FOR loop. Next, the index counter variable, v_counter, is evaluated using the IF-THEN statement so that only the first four records of the index-by table are displayed on the screen. When run, this script produces the following output: First Name(1): A. Last Name(1): Tucker Enrollments(1): 1 First Name(2): Adele Last Name(2): Rothstein Enrollments(2): 1 First Name(3): Adrienne Last Name(3): Lopez Enrollments(3): 1 First Name(4): Al Last Name(4): Jamerncy Enrollments(4): 1 PL/SQL procedure successfully completed. LAB 16.3 Lab 16.3 Exercises 377 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. ▼ TRY IT YOURSELF In this chapter, you’ve learned about various types of records, nested records, and collections of records. Here are some projects that will help you test the depth of your understanding: 1) Create an associative array with the element type of a user-defined record.This record should contain the first name, last name, and total number of courses that a particular instructor teaches. Display the records of the associative array on the screen. 2) Modify the script you just created. Instead of using an associative array, use a nested table. 3) Modify the script you just created. Instead of using a nested table, use a varray. 4) Create a user-defined record with four fields: course_no, description, cost, and prerequisite_rec.The last field, prerequisite_rec, should be a user-defined record with three fields: prereq_no, prereq_desc, and prereq_cost. For any ten courses that have a prerequisite course, populate the user-defined record with all the corresponding data, and display its information on the screen. The projects in this section are meant to have you use all the skills you have acquired throughout this chapter.The answers to these projects can be found in Appendix D and on this book’s companion Web site.Visit the Web site periodically to share and discuss your answers. 378 Try it Yourself Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. CHAPTER 17 Native Dynamic SQL CHAPTER OBJECTIVES In this chapter, you will learn about . EXECUTE IMMEDIATE statements . OPEN-FOR, FETCH, and CLOSE statements Generally, PL/SQL applications perform a specific task and manipulate a static set of tables. For example, a stored procedure might accept a student ID and return the student’s first and last names. In such a procedure, a SELECT state- ment is known in advance and is compiled as part of the procedure. Such SELECT statements are called static because they do not change from execution to execution. Now, consider a different type of PL/SQL application in which SQL statements are built on the fly, based on a set of parameters specified at runtime. For example, an application might need to build various reports based on SQL state- ments where table and column names are not known in advance, or the sorting and grouping of data are specified by a user requesting a report. Similarly, another application might need to create or drop tables or other database objects based on the action specified by a user at runtime. Because these SQL statements are generated on the fly and might change from time to time, they are called dynamic. PL/SQL has a feature called native dynamic SQL (dynamic SQL for short) that helps you build applications similar to those just described. The use of dynamic SQL makes such applications flexible, versatile, and concise because it eliminates the need for complicated programming approaches. Native dynamic SQL is more convenient to use than the Oracle-supplied package DBMS_SQL, which has similar functionality. In this chapter you will learn how to create and use dynamic SQL. Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. LAB 17.1 EXECUTE IMMEDIATE Statements LAB OBJECTIVE After completing this lab, you will be able to . Use the EXECUTE IMMEDIATE statement Generally, dynamic SQL statements are built by your program and are stored as character strings based on the parameters specified at runtime. These strings must contain valid SQL statements or PL/SQL code. Consider the following dynamic SQL statement: FOR EXAMPLE 'SELECT first_name, last_name FROM student WHERE student_id = :student_id' This SELECT statement returns a student’s first and last name for a given student ID. The value of the student ID is not known in advance and is specified with the help of a bind argument, :student_id. The bind argument is a placeholder for an undeclared identifier, and its name must be prefixed by a colon. As a result, PL/SQL does not differentiate between the following statements: 'SELECT first_name, last_name FROM student WHERE student_id = :student_id' 'SELECT first_name, last_name FROM student WHERE student_id = :id' To process dynamic SQL statements, you use EXECUTE IMMEDIATE or OPEN-FOR, FETCH, and CLOSE statements. EXECUTE IMMEDIATE is used for single-row SELECT statements, all DML statements, and DDL statements. OPEN-FOR, FETCH, and CLOSE statements are used for multirow SELECTs and reference cursors. BY THE WAY To improve the performance of dynamic SQL statements you can also use BULK EXECUTE IMMEDI- ATE, BULK FETCH, FORALL, and COLLECT INTO statements. However, these statements are outside the scope of this book and therefore are not covered.You can find detailed explanations and examples of their usage in the online Oracle help. LAB 17.1 380 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. THE EXECUTE IMMEDIATE STATEMENT The EXECUTE IMMEDIATE statement parses a dynamic statement or a PL/SQL block for imme- diate execution. Its structure is as follows (the reserved words and phrases in square brackets are optional): EXECUTE IMMEDIATE dynamic_SQL_string [INTO defined_variable1 , defined_variable2 , ] [USING [IN | OUT | IN OUT] bind_argument1 , bind_argument2 , ][{RETURNING | RETURN} field1 , field2 , INTO bind_argument1 , bind_argument2 , ] dynamic_SQL_string is a string that contains a valid SQL statement or a PL/SQL block. The INTO clause contains the list of predefined variables that hold values returned by the SELECT statement. This clause is used when a dynamic SQL statement returns a single row similar to a static SELECT INTO statement. Next, the USING clause contains a list of bind argu- ments whose values are passed to the dynamic SQL statement or PL/SQL block. IN, OUT, and IN OUT are modes for bind arguments. If no mode is specified, all bind arguments listed in the USING clause are in IN mode. Finally, the RETURNING INTO or RETURN clause contains a list of bind arguments that store values returned by the dynamic SQL statement or PL/SQL block. Similar to the USING clause, the RETURNING INTO clause may also contain various argument modes; however, if no mode is specified, all bind arguments are in OUT mode. DID YOU KNOW? When an EXECUTE IMMEDIATE statement contains both USING and RETURNING INTO clauses, the USING clause may specify only IN arguments. FOR EXAMPLE DECLARE sql_stmt VARCHAR2(100); plsql_block VARCHAR2(300); v_zip VARCHAR2(5) := '11106'; v_total_students NUMBER; v_new_zip VARCHAR2(5); v_student_id NUMBER := 151; BEGIN Create table MY_STUDENT sql_stmt := 'CREATE TABLE my_student '|| 'AS SELECT * FROM student WHERE zip = '||v_zip; EXECUTE IMMEDIATE sql_stmt; Select total number of records from MY_STUDENT table and display results on the screen EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM my_student' INTO v_total_students; DBMS_OUTPUT.PUT_LINE ('Students added: '||v_total_students); LAB 17.1 EXECUTE IMMEDIATE Statements 381 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. [...]... procedures Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark This page intentionally left blank Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark CHAPTER 18 Bulk SQL CHAPTER OBJECTIVES In this chapter, you will learn about The FORALL statement The BULK COLLECT clause I n Chapter 1, PL/SQL Concepts,” you learned that the PL/SQL engine sends SQL statements... the dynamic SQL statement used by the previous version (ch17_1b.sql) sql_stmt := 'SELECT a.first_name, a.last_name, a.street_address'|| ' ,b.city, b.state, b.zip' || Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Lab 17.1 Exercises LAB 17.1 391 ' FROM student a, zipcode b' ' WHERE a.zip = b.zip' ' AND student_id = :1'; || || has been replaced by sql_stmt := 'SELECT a.first_name,... separate the GROUP BY clause This step is necessary because after the strings are concatenated, the resulting SELECT statement looks like this: SELECT zip, COUNT(*) total FROM student GROUP BY zip If no space is added after the STUDENT table, the resulting SELECT statement SELECT zip, COUNT(*) total FROM studentGROUP BY zip causes this error: ERROR: ORA-00933: SQL command not properly ended PL/SQL procedure... a string variable to hold a dynamic SQL statement, and two variables, v_zip and v_total, to hold data returned by the cursor Finally, you define a counter variable so that only the first ten rows returned by the cursor are displayed on the screen Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Lab 17.2 Exercises LAB 17.2 397 In the executable portion of the script, you... PL/SQL procedure successfully completed Enter value for sv_table_name: instructor old 10: v_table_name VARCHAR2(20) := '&sv_table_name'; new 10: v_table_name VARCHAR2(20) := 'instructor'; Totals from instructor table Zip code: 10005 Total: 1 Zip code: 10015 Total: 3 Zip code: 10025 Total: 4 Zip code: 10035 Total: 1 PL/SQL procedure successfully completed Please purchase PDF Split-Merge on www.verypdf.com... a PL/SQL block is terminated by a slash: FOR EXAMPLE DECLARE plsql_block VARCHAR2(300); BEGIN Select current date and display it on the screen plsql_block := 'DECLARE ' || ' v_date DATE; ' || 'BEGIN ' || ' SELECT SYSDATE INTO v_date FROM DUAL; '|| ' DBMS_OUTPUT.PUT_LINE (TO_CHAR(v_date, ''DD-MON-YYYY''));'|| 'END;' ; EXECUTE IMMEDIATE plsql_block; END; Please purchase PDF Split-Merge on www.verypdf.com... variables TYPE row_num_type IS TABLE OF NUMBER INDEX BY PLS_INTEGER; TYPE row_text_type IS TABLE OF VARCHAR2(10) INDEX BY PLS_INTEGER; row_num_tab row_num_type; row_text_tab row_text_type; v_total NUMBER; BEGIN Populate collections FOR i IN 1 10 LOOP row_num_tab(i) := i; row_text_tab(i) := 'row '||i; END LOOP; Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark LAB 18.1 The FORALL... TABLE test; DECLARE Define collection types and variables TYPE row_num_type IS TABLE OF NUMBER INDEX BY PLS_INTEGER; TYPE row_text_type IS TABLE OF VARCHAR2(10) INDEX BY PLS_INTEGER; row_num_tab row_num_type; row_text_tab row_text_type; v_total NUMBER; Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark The FORALL Statement LAB 18.1 407 v_start_time INTEGER; v_end_time INTEGER;... v_start_time)); COMMIT; END; To calculate execution times of the FOR loop and the FORALL statement, you employ the GET_TIME function from the DBMS_UTILITY package that is owned by the Oracle user SYS Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark ... v_last_name These variables contain results returned by the SELECT statement The USING clause contains the variable v_student_id, which is used to pass a value to the SELECT statement at runtime Finally, two DBMS_OUTPUT.PUT_LINE statements are used to display the results of the SELECT statement on the screen Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark LAB 17.1 Lab 17.1 . Tucker Names(6): Mithane PL/SQL procedure successfully completed. LAB 16.2 372 Lab 16.2 Exercises Please purchase PDF Split-Merge on www.verypdf.com to remove. Jamerncy Enrollments(4): 1 PL/SQL procedure successfully completed. LAB 16.3 Lab 16.3 Exercises 377 Please purchase PDF Split-Merge on www.verypdf.com to remove

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

TỪ KHÓA LIÊN QUAN