402Part II: SQL and SQL*PlusWithin the into table clause, you can use the recnum keyword to pps

105 472 0
402Part II: SQL and SQL*PlusWithin the into table clause, you can use the recnum keyword to pps

Đ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

ORACLE Color profile: Generic CMYK printer profile Composite Default screen 402 Series TIGHT / Oracle9i: The Complete Reference / Loney, Koch / 222521-1 / Chapter 21 Blind Folio 21:402 Part II: SQL and SQL*Plus Within the into table clause, you can use the recnum keyword to assign a record number to each logical record as it is read from the datafile, and that value will be inserted into the assigned column of the table The constant keyword allows you to assign a constant value to a column during the load For character columns, enclose the constant value within single quotes If you use the sysdate keyword, the selected column will be populated with the current system date and time CheckOutDate SYSDATE If you use the sequence option, SQL*Loader will maintain a sequence of values during the load As records are processed, the sequence value will be increased by the increment you specify If the rows fail during insert (and are sent to the bad file), those sequence values will not be reused If you use the max keyword within the sequence option, the sequence values will use the current maximum value of the column as the starting point for the sequence The following listing shows the use of the sequence option: Seqnum_col SEQUENCE(MAX,1) You can also specify the starting value and increment for a sequence to use when inserting The following example inserts values starting with a value of 100, incrementing by If a row is rejected during the insert, its sequence value is skipped Seqnum_col SEQUENCE(100,2) If you store numbers in VARCHAR2 columns, avoid using the sequence option for those columns For example, if your table already contains the values through 10 in a VARCHAR2 column, then the maximum value within that column is 9—the greatest character string Using that as the basis for a sequence option will cause SQL*Loader to attempt to insert a record using 10 as the newly created value—and that may conflict with the existing record SQL*Loader control files can support complex logic and business rules For example, your input data for a column holding monetary values may have an implied decimal; 9990 would be inserted as 99.90 In SQL*Loader, you could insert this by performing the calculation during the data load: money_amount position (20:28) external decimal(9) ":tax_amount/100" See the “SQL*Loader Case Studies” of the Oracle9i Utilities Guide for additional SQL*Loader examples and sample control files Managing Data Loads Loading large data volumes is a batch operation Batch operations should not be performed concurrently with the small transactions prevalent in many database applications If you have many concurrent users executing small transactions against a table, you should schedule your batch operations against that table to occur at a time when no users are accessing the table Oracle maintains read consistency for users’ queries If you execute the SQL*Loader job against the table at the same time that other users are querying the table, Oracle will internally P:\010Comp\Oracle8\521-1\CD\Ventura\book.vp Friday, July 19, 2002 4:13:02 PM ORACLE Color profile: Generic CMYK printer profile Composite Default screen Series TIGHT / Oracle9i: The Complete Reference / Loney, Koch / 222521-1 / Chapter 21 Blind Folio 21:403 Chapter 21: Using SQL*Loader to Load Data maintain undo entries to enable those users to see their data as it existed when they first queried the data To minimize the amount of work Oracle must perform to maintain read consistency (and to minimize the associated performance degradation caused by this overhead), schedule your long-running data load jobs to be performed when few other actions are occurring in the database In particular, avoid contention with other accesses of the same table Design your data load processing to be easy to maintain and reuse Establish guidelines for the structure and format of the input datafiles The more standardized the input data formats are, the simpler it will be to reuse old control files for the data loads For repeated scheduled loads into the same table, your goal should be to reuse the same control file each time Following each load, you will need to review and move the log, bad, data, and discard files so they not accidentally get overwritten Within the control file, use comments to indicate any special processing functions being performed To create a comment within the control file, begin the line with two dashes, as shown in the following example: Limit the load to LA employees: when Location='LA' If you have properly commented your control file, you will increase the chance that it can be reused during future loads You will also simplify the maintenance of the data load process itself, as described in the next section Repeating Data Loads Data loads not always work exactly as planned Many variables are involved in a data load, and not all of them will always be under your control For example, the owner of the source data may change its data formatting, invalidating part of your control file Business rules may change, forcing additional changes Database structures and space availability may change, further affecting your ability to load the data In an ideal case, a data load will either fully succeed or fully fail However, in many cases, a data load will partially succeed, making the recovery process more difficult If some of the records have been inserted into the table, then attempting to reinsert those records should result in a primary key violation If you are generating the primary key value during the insert (via the sequence option), then those rows may not fail the second time—and will be inserted twice To determine where a load failed, use the log file The log file will record the commit points as well as the errors encountered All of the rejected records should be in either the bad file or the discard file You can minimize the recovery effort by forcing the load to fail if many errors are encountered To force the load to abort before a large number of errors is encountered, use the errors keyword of the SQLLDR command You can also use the discardmax keyword to limit the number of discarded records permitted before the load aborts If you set errors to 0, the first error will cause the load to fail What if that load fails after 100 records have been inserted? You will have two options: identify and delete the inserted records and reapply the whole load, or skip the successfully inserted records You can use the skip keyword of SQLLDR to skip the first 100 records during its load processing The load will then continue with record 101 (which, we hope, has been fixed prior to the reload attempt) If you cannot identify the rows that have just been loaded into the table, you will need to use the skip option during the restart process P:\010Comp\Oracle8\521-1\CD\Ventura\book.vp Friday, July 19, 2002 4:13:02 PM 403 ORACLE Color profile: Generic CMYK printer profile Composite Default screen 404 Series TIGHT / Oracle9i: The Complete Reference / Loney, Koch / 222521-1 / Chapter 21 Blind Folio 21:404 Part II: SQL and SQL*Plus The proper settings for errors and discardmax depend on the load If you have full control over the data load process, and the data is properly “cleaned” before being extracted to a load file, you may have very little tolerance for errors and discards On the other hand, if you not have control over the source for the input datafile, you need to set errors and discardmax high enough to allow the load to complete After the load has completed, you need to review the log file, correct the data in the bad file, and reload the data using the original bad file as the new input file If rows have been incorrectly discarded, you need to an additional load using the original discard file as the new input file After modifying the errant CategoryName value, you can rerun the BOOKSHELF table load example using the original bookshelf.dat file During the reload, you have two options when using the original input datafile: s Skip the first row by specifying skip=1 in the SQLLDR command line s Attempt to load both rows, whereby the first row fails because it has already been loaded (and thus causes a primary key violation) Alternatively, you can use the bad file as the new input datafile and not worry about errors and skipped rows Tuning Data Loads In addition to running the data load processes at off-peak hours, you can take other steps to improve the load performance The following steps all impact your overall database environment, and must be coordinated with the database administrator The tuning of a data load should not be allowed to have a negative impact on the database or on the business processes it supports First, batch data loads may be timed to occur while the database is in NOARCHIVELOG mode While in NOARCHIVELOG mode, the database does not keep an archive of its online redo log files prior to overwriting them Eliminating the archiving process improves the performance of transactions Since the data is being loaded from a file, you can re-create the loaded data at a later time by reloading the datafile rather than recovering it from an archived redo log file However, there are significant potential issues with disabling NOARCHIVELOG mode You will not be able to perform a point-in-time recovery of the database unless archiving is enabled If there are non-batch transactions performed in the database, you will probably need to run the database in ARCHIVELOG mode all the time, including during your loads Furthermore, switching between ARCHIVELOG and NOARCHIVELOG modes requires you to shut down the instance If you switch the instance to NOARCHIVELOG mode, perform your data load, and then switch the instance back to ARCHIVELOG mode, you should perform a backup of the database (see Chapter 40) immediately following the restart Instead of running the entire database in NOARCHIVELOG mode, you can disable archiving for your data load process by using the unrecoverable keyword within SQL*Loader The unrecoverable option disables the writing of redo log entries for the transactions within the data load You should only use this option if you will be able to re-create the transactions from the input files during a recovery If you follow this strategy, you must have adequate space to store old input files in case they are needed for future recoveries The unrecoverable option is only available for Direct Path loads, as described in the next section P:\010Comp\Oracle8\521-1\CD\Ventura\book.vp Friday, July 19, 2002 4:13:03 PM ORACLE Color profile: Generic CMYK printer profile Composite Default screen Series TIGHT / Oracle9i: The Complete Reference / Loney, Koch / 222521-1 / Chapter 21 Blind Folio 21:405 Chapter 21: Using SQL*Loader to Load Data Rather than control the redo log activity at the load process level, you can control it at the table or partition level If you define an object as nologging, then block-level inserts performed by SQL*Loader Direct Path loading and the insert /*+ APPEND */ command will not generate redo log entries If your operating environment has multiple processors, you can take advantage of the CPUs by parallelizing the data load The parallel option of SQLLDR, as described in the next section, uses multiple concurrent data load processes to reduce the overall time required to load the data In addition to these approaches, you should work with your database administrator to make sure the database environment and structures are properly tuned for data loads Tuning efforts should include the following: s Preallocate space for the table, to minimize dynamic extensions during the loads s Allocate sufficient memory resources to the shared memory areas, including the log buffer area s Streamline the data writing process by creating multiple database writer (DBWR) processes for the database s Remove any unnecessary triggers during the data loads If possible, disable or remove the triggers prior to the load, and perform the trigger operations on the loaded data manually after it has been loaded s Remove or disable any unnecessary constraints on the table You can use SQL*Loader to dynamically disable and re-enable constraints s Remove any indexes on the tables If the data has been properly cleaned prior to the data load, then uniqueness checks and foreign key validations will not be necessary during the loads Dropping indexes prior to data loads significantly improves performance If you leave indexes on during a data load, Oracle must manage and rebalance the index with each inserted record The larger your data load is, the more work Oracle will have to to manage the associated indexes If you can, you should consider dropping the indexes prior to the load and then re-creating them after the load completes The only time indexes not cause a penalty for data load performance is during a Direct Path load, as described in the next section Direct Path Loading SQL*Loader, when inserting records, generates a large number of insert statements To avoid the overhead associated with using a large number of inserts, you may use the Direct Path option in SQL*Loader The Direct Path option creates preformatted data blocks and inserts those blocks into the table As a result, the performance of your load can dramatically improve To use the Direct Path option, you must not be performing any functions on the values being read from the input file Any indexes on the table being loaded will be placed into a temporary DIRECT LOAD state (you can query the index status from USER_INDEXES) Oracle will move the old index values to a temporary index it creates and manages Once the load has completed, the old index values will be merged with the new values to create the new index, and Oracle will drop the temporary index it created When the index is once again valid, its status will change to VALID To minimize P:\010Comp\Oracle8\521-1\CD\Ventura\book.vp Friday, July 19, 2002 4:13:03 PM 405 ORACLE Color profile: Generic CMYK printer profile Composite Default screen 406 Series TIGHT / Oracle9i: The Complete Reference / Loney, Koch / 222521-1 / Chapter 21 Blind Folio 21:406 Part II: SQL and SQL*Plus the amount of space necessary for the temporary index, presort the data by the indexed columns The name of the index for which the data is presorted should be specified via a sorted indexes clause in the control file To use the direct path option, specify DIRECT=TRUE as a keyword on the SQLLDR command line or include this option in the control file If you use the Direct Path option, you can use the unrecoverable keyword to improve your data load performance This instructs Oracle not to generate redo log entries for the load If you need to recover the database at a later point, you will need to re-execute the data load in order to recover the table’s data All conventional path loads are recoverable, and all Direct Path loads are recoverable by default Direct Path loads are faster than conventional loads, and unrecoverable Direct Path loads are faster still Since performing unrecoverable loads impacts your recovery operations, you need to weigh the costs of that impact against the performance benefit you will realize If your hardware environment has additional resources available during the load, you can use the parallel Direct Path load option to divide the data load work among multiple processes The parallel Direct Path operations may complete the load job faster than a single Direct Path load Instead of using the parallel option, you could partition the table being loaded (see Chapter 18) Since SQL*Loader allows you to load a single partition, you could execute multiple concurrent SQL*Loader jobs to populate the separate partitions of a partitioned table This method requires more database administration work (to configure and manage the partitions), but it gives you more flexibility in the parallelization and scheduling of the load jobs As of Oracle9i, you can take advantage of multithreaded loading functionality for Direct Path loads to convert column arrays to stream buffers and perform stream buffer loading in parallel Use the streamsize parameter and multithreading flag to enable this feature Direct Path loading may impact the space required for the table’s data Since Direct Path loading inserts blocks of data, it does not follow the usual methods for allocating space within a table The blocks are inserted at the end of the table, after its high-water mark, which is the highest block into which the table’s data has ever been written If you insert 100 blocks worth of data into a table and then delete all of the rows, the high-water mark for the table will still be set at 100 If you then perform a conventional SQL*Loader data load, the rows will be inserted into the already allocated blocks If you instead perform a Direct Path load, Oracle will insert new blocks of data following block 100, potentially increasing the space allocation for the table The only way to lower the high-water mark for a table is to truncate it (which deletes all rows and cannot be rolled back) or to drop and re-create it You should work with your database administrator to identify space issues prior to starting your load Additional Oracle9i Enhancements In addition to features noted earlier in this chapter, SQL*Loader features support for Unicode and expanded datatypes As of Oracle9i, SQL*Loader can load integer and zoned/packed decimal datatypes across platforms with different byte ordering and accept EBCDIC-based zoned or packed decimal data encoded in IBM format SQL*Loader also offers support for loading XML columns, loading object types with subtypes (see Chapter 30), and Unicode (UTF16 character set) P:\010Comp\Oracle8\521-1\CD\Ventura\book.vp Friday, July 19, 2002 4:13:03 PM ORACLE Color profile: Generic CMYK printer profile Composite Default screen Series TIGHT / Oracle9i: The Complete Reference / Loney, Koch / 222521-1 / Chapter 21 Blind Folio 21:407 Chapter 21: Using SQL*Loader to Load Data SQL*Loader also provides native support for the new Oracle9i date, time, and interval-related datatypes (see Chapter 9) If a SQL*Loader job fails, you may be able to resume it where it failed using the resumable, resumable_name, and resumable_timeout options For example, if the segment to which the loader job was writing could not extend, you can disable the load job, fix the space allocation problem, and resume the job Your ability to perform these actions depends on the configuration of the database; work with your DBA to make sure the resumable features are enabled and adequate undo history is maintained for your purposes As of Oracle9i, you can access external files as if they are tables inside the database This “external table” feature, described in Chapter 25, allows you to potentially avoid loading large volumes of data into the database The syntax for external table definitions very closely resembles that of the SQL*Loader control file Although they are limited in some significant ways (you cannot perform DML on external tables, for example), you should consider external tables as alternatives to data loads See Chapter 25 for implementation details P:\010Comp\Oracle8\521-1\CD\Ventura\book.vp Friday, July 19, 2002 4:13:04 PM 407 ORACLE Color profile: Generic CMYK printer profile Composite Default screen P:\010Comp\Oracle8\521-1\CD\Ventura\book.vp Friday, July 19, 2002 4:13:04 PM Series TIGHT / Oracle9i: The Complete Reference / Loney, Koch / 222521-1 / Chapter 21 Blind Folio 21:408 ORACLE Color profile: Generic CMYK printer profile Composite Default screen Series TIGHT / Oracle9i: The Complete Reference / Loney, Koch / 222521-1 / Chapter 22 Blind Folio 22:409 CHAPTER 22 Accessing Remote Data P:\010Comp\Oracle8\521-1\CD\Ventura\book.vp Friday, July 19, 2002 4:13:04 PM ORACLE Color profile: Generic CMYK printer profile Composite Default screen 410 Series TIGHT / Oracle9i: The Complete Reference / Loney, Koch / 222521-1 / Chapter 22 Blind Folio 22:410 Part II: SQL and SQL*Plus s your databases grow in size and number, you will very likely need to share data among them Sharing data requires a method of locating and accessing the data In Oracle, remote data accesses such as queries and updates are enabled through the use of database links As described in this chapter, database links allow users to treat a group of distributed databases as if they were a single, integrated database In this chapter, you will also find information about direct connections to remote databases, such as those used in client-server applications A Database Links Database links tell Oracle how to get from one database to another You may also specify the access path in an ad hoc fashion (see “Dynamic Links: Using the SQLPLUS copy Command,” later in this chapter) If you will frequently use the same connection to a remote database, then a database link is appropriate How a Database Link Works A database link requires that Oracle Net (previously known as SQL*Net and Net8) be running on each of the machines (hosts) involved in the remote database access Oracle Net is usually started by the database administrator (DBA) or the system manager A sample architecture for a remote access using a database link is shown in Figure 22-1 This figure shows two hosts, each running Oracle Net There is a database on each of the hosts A database link establishes a connection from the first database (named LOCAL, on the Branch host) to the second database (named REMOTE, on the Headquarters host) The database link shown in Figure 22-1 is located in the Local database Database links specify the following connection information: s The communications protocol (such as TCP/IP) to use during the connection s The host on which the remote database resides s The name of the database on the remote host s The name of a valid account in the remote database s The password for that account FIGURE 22-1 Sample architecture for a database link P:\010Comp\Oracle8\521-1\CD\Ventura\book.vp Friday, July 19, 2002 4:13:05 PM ORACLE Color profile: Generic CMYK printer profile Composite Default screen Series TIGHT / Oracle9i: The Complete Reference / Loney, Koch / 222521-1 / Chapter 22 Blind Folio 22:411 Chapter 22: Accessing Remote Data When used, a database link actually logs in as a user in the remote database, and then logs out when the remote data access is complete A database link can be private, owned by a single user, or public, in which case all users in the Local database can use the link The syntax for creating a database link is shown in “Syntax for Database Links,” later in this chapter Using a Database Link for Remote Queries If you are a user in the Local database shown in Figure 22-1, you can access objects in the Remote database via a database link To this, simply append the database link name to the name of any table or view that is accessible to the remote account When appending the database link name to a table or view name, you must precede the database link name with an @ sign For local tables, you reference the table name in the from clause: select * from BOOKSHELF; For remote tables, use a database link named REMOTE_CONNECT In the from clause, reference the table name followed by @REMOTE_CONNECT: select * from BOOKSHELF@REMOTE_CONNECT; When the database link in the preceding query is used, Oracle will log in to the database specified by the database link, using the username and password provided by the link It will then query the BOOKSHELF table in that account and return the data to the user who initiated the query This is shown graphically in Figure 22-2 The REMOTE_CONNECT database link shown in Figure 22-2 is located in the Local database As shown in Figure 22-2, logging in to the Local database and using the REMOTE_CONNECT database link in your from clause returns the same results as logging in directly to the remote database and executing the query without the database link It makes the remote database seem local NOTE The maximum number of database links that can be used in a single query is set via the OPEN_LINKS parameter in the database’s initialization parameter file This parameter defaults to four FIGURE 22-2 Using a database link for a remote query P:\010Comp\Oracle8\521-1\CD\Ventura\book.vp Friday, July 19, 2002 4:13:05 PM 411 ORACLE Color profile: Generic CMYK printer profile Composite Default screen 492 Series TIGHT / Oracle9i: The Complete Reference / Loney, Koch / 222521-1 / Chapter 27 Blind Folio 27:492 Part III: PL/SQL The first variable declared is pi, which is set to a constant value via the constant keyword Because it is declared as a constant, the value of the variable pi cannot be changed in the Executable Commands section The value is assigned via the := operator: pi constant NUMBER(9,7) := 3.1415927; You can also assign constant values via the default keyword: pi NUMBER(9,7) DEFAULT 3.1415927; The next two variables are defined but are not given default values: radius INTEGER(5); area NUMBER(14,2); You can assign an initial value to a variable in the Declarations section To set an initial value for a variable, simply follow its datatype specification with the value assignment, as shown in the following listing: radius INTEGER(5) := 3; In the example, the datatypes include NUMBER and INTEGER PL/SQL datatypes include all of the valid SQL datatypes as well as complex datatypes based on query structures Table 27-1 lists the supported PL/SQL datatypes In the following example, a cursor is declared to retrieve a record from the RADIUS_VALS table RADIUS_VALS is a table with one column, named Radius, that holds radius values to be used in these examples The cursor is declared in the Declarations section, and a variable named rad_val is declared with a datatype based on the cursor’s results declare pi constant NUMBER(9,7) := 3.1415927; area NUMBER(14,2); cursor rad_cursor is select * from RADIUS_VALS; rad_val rad_cursor%ROWTYPE; begin open rad_cursor; fetch rad_cursor into rad_val; area := pi*power(rad_val.radius,2); insert into AREAS values (rad_val.radius, area); close rad_cursor; end; For this example, the table RADIUS_VALS contains a single row with a Radius value of In the first part of the Declarations section, the pi and area variables are defined, as they were in the examples earlier in this chapter The radius variable is not defined; instead, a cursor named rad_cursor is defined The cursor definition consists of a cursor name (rad_cursor) and a query P:\010Comp\Oracle8\521-1\CD\Ventura\book.vp Friday, July 19, 2002 4:13:36 PM ORACLE Color profile: Generic CMYK printer profile Composite Default screen Series TIGHT / Oracle9i: The Complete Reference / Loney, Koch / 222521-1 / Chapter 27 Blind Folio 27:493 Chapter 27: An Introduction to PL/SQL Scalar Datatypes BINARY_INTEGER INT NVARCHAR2 STRING BOOLEAN INTEGER NUMBER TIMESTAMP CHAR INTERVAL DAY TO SECOND NUMERIC TIMESTAMP WITH LOCAL TIME ZONE CHARACTER INTERVAL YEAR TO MONTH PLS_INTEGER TIMESTAMP WITH TIME ZONE DATE LONG POSITIVE UROWID DEC LONG RAW POSITIVEN VARCHAR DECIMAL NATURAL REAL VARCHAR2 DOUBLE PRECISION NATURALN SIGNTYPE RAW FLOAT NCHAR SMALLINT ROWID TABLE VARRAY Composite Types RECORD Reference Types REF object_type REF CURSOR LOB Types BFILE TABLE 27-1 BLOB CLOB NCLOB PL/SQL Datatypes (select * from RADIUS_VALS;) A cursor holds the results of a query for processing by other commands within the PL/SQL block: declare pi constant NUMBER(9,7) := 3.1415927; area NUMBER(14,2); cursor rad_cursor is select * from RADIUS_VALS; A final declaration creates a variable whose structure is anchored by the cursor’s result set: rad_val rad_cursor%ROWTYPE; The rad_val variable will be able to reference each column of the query’s result set In this example, the query only returns a single column, but if the table contained multiple columns, you would be able to reference all of them via the rad_val variable P:\010Comp\Oracle8\521-1\CD\Ventura\book.vp Friday, July 19, 2002 4:13:36 PM 493 ORACLE Color profile: Generic CMYK printer profile Composite Default screen 494 Series TIGHT / Oracle9i: The Complete Reference / Loney, Koch / 222521-1 / Chapter 27 Blind Folio 27:494 Part III: PL/SQL In addition to the %ROWTYPE declaration, you can use the %TYPE declaration to inherit datatype information If you use the %ROWTYPE declaration, the variable inherits the column and datatype information for all the columns in the cursor’s result set If you use the %TYPE declaration, then the variable only inherits the definition of the column used to define it You can even base %TYPE definitions on cursors, as shown in the following example cursor rad_cursor is select * from RADIUS_VALS; rad_val rad_cursor%ROWTYPE; rad_val_radius rad_val.Radius%TYPE; In the preceding listing, the rad_val variable inherits the datatypes of the result set of the rad_ cursor cursor The rad_val_radius variable inherits the datatype of the Radius column within the rad_val variable The advantage of datatype anchoring using %ROWTYPE and %TYPE definitions is that it makes the datatype definitions in your PL/SQL code independent of the underlying data structures If the RADIUS_VALS Radius column is changed from a NUMBER(5) datatype to a NUMBER(4,2) datatype, you not need to modify your PL/SQL code; the datatype assigned to the associated variables will be determined dynamically at runtime Executable Commands Section In the Executable Commands section, you manipulate the variables and cursors declared in the Declarations section of your PL/SQL block The Executable Commands section always starts with the keyword begin In the following listing, the first PL/SQL block example from the Declarations section is repeated: the area of a circle is calculated, and the results are inserted into the AREAS table: declare pi constant NUMBER(9,7) := 3.1415927; radius INTEGER(5); area NUMBER(14,2); begin radius := 3; area := pi*power(radius,2); insert into AREAS values (radius, area); end; In the preceding listing, the Executable Commands section is begin radius := 3; area := pi*power(radius,2); insert into AREAS values (radius, area); end; Following the begin keyword, the PL/SQL block’s work begins First, a value is assigned to the radius variable, and the radius variable and the pi constant value are used to determine the value of the area variable The Radius and Area values are then inserted into the AREAS table P:\010Comp\Oracle8\521-1\CD\Ventura\book.vp Friday, July 19, 2002 4:13:36 PM ORACLE Color profile: Generic CMYK printer profile Composite Default screen Series TIGHT / Oracle9i: The Complete Reference / Loney, Koch / 222521-1 / Chapter 27 Blind Folio 27:495 Chapter 27: An Introduction to PL/SQL The Executable Commands section of the PL/SQL block may contain commands that execute the cursors declared in the Declarations section In the following example (from the “Declarations Section” section of this chapter), the Executable Commands section features several commands that reference the rad_cursor cursor: declare pi constant NUMBER(9,7) := 3.1415927; area NUMBER(14,2); cursor rad_cursor is select * from RADIUS_VALS; rad_val rad_cursor%ROWTYPE; begin open rad_cursor; fetch rad_cursor into rad_val; area := pi*power(rad_val.radius,2); insert into AREAS values (rad_val.radius, area); close rad_cursor; end; In the first command involving the cursor, the open command is used: open rad_cursor; When the rad_cursor cursor is opened, the query declared for that cursor is executed and the records to be returned are identified Next, records are fetched from the cursor: fetch rad_cursor into rad_val; In the Declarations section, the rad_val variable was declared to anchor its datatypes to the rad_cursor cursor: cursor rad_cursor is select * from RADIUS_VALS; rad_val rad_cursor%ROWTYPE; When you fetch a record from the cursor into the rad_val variable, you can still address each column value selected via the cursor’s query When the cursor’s data is no longer needed, you can close the cursor, as shown in the following listing: close rad_cursor; The Executable Commands section may contain conditional logic, such as if commands and loops In the following sections, you will see examples of each of the major types of flow-control operations permitted in PL/SQL You can use the flow-control operations to alter the manner in which the fetched records and executable commands are managed P:\010Comp\Oracle8\521-1\CD\Ventura\book.vp Friday, July 19, 2002 4:13:37 PM 495 ORACLE Color profile: Generic CMYK printer profile Composite Default screen 496 Series TIGHT / Oracle9i: The Complete Reference / Loney, Koch / 222521-1 / Chapter 27 Blind Folio 27:496 Part III: PL/SQL Conditional Logic Within PL/SQL, you can use if, else, elsif, and case commands to control the flow of commands within the Executable Commands section The formats of the if clauses are shown in the following listing: if then elsif then else end if; You can nest if conditions within each other, as shown in the following listing: then if then end if; else end if; if By nesting if conditions, you can quickly develop complex logic flows within your Executable Commands section When nesting if conditions, make sure you are not making the flow control more complex than it needs to be; always check to see whether logical conditions can be combined into simpler orders The area of a circle example used in the previous section will now be modified to include conditional logic In the following listing, the Executable Commands section of the PL/SQL block has been modified to include if and then commands: declare pi constant NUMBER(9,7) := 3.1415927; area NUMBER(14,2); cursor rad_cursor is select * from RADIUS_VALS; rad_val rad_cursor%ROWTYPE; begin open rad_cursor; fetch rad_cursor into rad_val; area := pi*power(rad_val.radius,2); if area >30 then insert into AREAS values (rad_val.radius, area); end if; close rad_cursor; end; P:\010Comp\Oracle8\521-1\CD\Ventura\book.vp Friday, July 19, 2002 4:13:37 PM ORACLE Color profile: Generic CMYK printer profile Composite Default screen Series TIGHT / Oracle9i: The Complete Reference / Loney, Koch / 222521-1 / Chapter 27 Blind Folio 27:497 Chapter 27: An Introduction to PL/SQL In the preceding listing, an if condition is used to control the flow of commands within the Executable Commands section of the PL/SQL block The flow-control commands are shown in the following listing: if area >30 then insert into AREAS values (rad_val.radius, area); end if; The flow-control commands in this example begin after the area variable’s value has been determined If the value is greater than 30, then a record will be inserted into the AREAS table; if the value is less than 30, then no record will be inserted into the table You can use this sort of flow control to direct which of several SQL statements are to be executed, based on the conditions in your if conditions The following listing shows syntax for flow control involving SQL commands: if area>30 then elsif area100; end loop; end; The loop section of the example establishes the flow control for the commands in the Executable Commands section of the PL/SQL block The steps within the loop are described in the following commented version of the loop commands: loop /* Calculate the area, based on the radius value area := pi*power(radius,2); /* Insert the current values into the AREAS table insert into AREAS values (radius, area); /* Increment the radius value by radius := radius+1; /* Evaluate the last calculated area If the value /* exceeds 100, then exit Otherwise, repeat the /* loop using the new radius value exit when area >100; /* Signal the end of the loop end loop; */ */ */ */ */ */ */ The loop should generate multiple entries in the AREAS table The first record will be the record generated by a Radius value of Once an area value exceeds 100, no more records will be inserted into the AREAS table Sample output following the execution of the PL/SQL block is shown in the following listing: select * from AREAS order by Radius; RADIUS AREA -3 28.27 50.27 78.54 113.1 Since the area value for a Radius value of exceeds 100, no further Radius values are processed and the PL/SQL block completes Simple Cursor Loops You can use the attributes of a cursor—such as whether or not any rows are left to be fetched—as the exit criteria for a loop In the following example, a cursor is executed until no more rows are P:\010Comp\Oracle8\521-1\CD\Ventura\book.vp Friday, July 19, 2002 4:13:38 PM ORACLE Color profile: Generic CMYK printer profile Composite Default screen Series TIGHT / Oracle9i: The Complete Reference / Loney, Koch / 222521-1 / Chapter 27 Blind Folio 27:499 Chapter 27: An Introduction to PL/SQL returned by the query To determine the status of the cursor, the cursor’s attributes are checked Cursors have four attributes you can use in your program: %FOUND A record can be fetched from the cursor %NOTFOUND No more records can be fetched from the cursor %ISOPEN The cursor has been opened %ROWCOUNT The number of rows fetched from the cursor so far The %FOUND, %NOTFOUND, and %ISOPEN cursor attributes are Booleans; they are set to either TRUE or FALSE Because they are Boolean attributes, you can evaluate their settings without explicitly matching them to values of TRUE or FALSE For example, the following command will cause an exit to occur when rad_cursor%NOTFOUND is TRUE: exit when rad_cursor%NOTFOUND; In the following listing, a simple loop is used to process multiple rows from a cursor: declare pi constant NUMBER(9,7) := 3.1415927; area NUMBER(14,2); cursor rad_cursor is select * from RADIUS_VALS; rad_val rad_cursor%ROWTYPE; begin open rad_cursor; loop fetch rad_cursor into rad_val; exit when rad_cursor%NOTFOUND; area := pi*power(rad_val.radius,2); insert into AREAS values (rad_val.radius, area); end loop; close rad_cursor; end; The loop section of the PL/SQL block uses values from the RADIUS_VALS table as its input Instead of basing the exit criteria on the Area value, the cursor’s %NOTFOUND attribute is checked If no more rows are found in the cursor, then %NOTFOUND will be TRUE—and thus, the loop will be exited The commented version of the loop is shown in the following listing: loop /* Within the loop, fetch a record fetch rad_cursor into rad_val; /* If the fetch attempt reveals no more /* records in the cursor, then exit the loop exit when rad_cursor%NOTFOUND; /* If the fetch attempt returned a record, /* then process the Radius value and insert /* a record into the AREAS table P:\010Comp\Oracle8\521-1\CD\Ventura\book.vp Friday, July 19, 2002 4:13:38 PM */ */ */ */ */ */ 499 ORACLE Color profile: Generic CMYK printer profile Composite Default screen 500 Series TIGHT / Oracle9i: The Complete Reference / Loney, Koch / 222521-1 / Chapter 27 Blind Folio 27:500 Part III: PL/SQL area := pi*power(rad_val.radius,2); insert into AREAS values (rad_val.radius, area); /* Signal the end of the loop */ end loop; When the preceding PL/SQL block is executed, every record in the RADIUS_VALS table will be processed by the loop So far, the RADIUS_VALS table only contains one record—a Radius value of Prior to executing the PL/SQL block for this section, add two new Radius values to the RADIUS_VALS table: and 10 The following listing shows the addition of the new records to the RADIUS_VALS table: insert into RADIUS_VALS values (4); insert into RADIUS_VALS values (10); commit; select * from RADIUS_VALS order by Radius; RADIUS -3 10 Once the new records have been added to the RADIUS_VALS table, execute the PL/SQL block shown earlier in this section The output of the PL/SQL block is shown in the following listing: select * from AREAS order by Radius; RADIUS AREA -3 28.27 50.27 10 314.16 The query of the AREAS table shows that every record in the RADIUS_VALS table was fetched from the cursor and processed Once there were no more records to process in the cursor, the loop was exited and the PL/SQL block completed FOR Loops In simple loops, the loop executes until an exit condition is met In a FOR loop, the loop executes a specified number of times An example of a FOR loop is shown in the following listing The FOR loop’s start is indicated by the keyword for, followed by the criteria used to determine when the processing is complete and the loop can be exited Since the number of times the loop is executed is set when the loop is begun, an exit command isn’t needed within the loop P:\010Comp\Oracle8\521-1\CD\Ventura\book.vp Friday, July 19, 2002 4:13:39 PM ORACLE Color profile: Generic CMYK printer profile Composite Default screen Series TIGHT / Oracle9i: The Complete Reference / Loney, Koch / 222521-1 / Chapter 27 Blind Folio 27:501 Chapter 27: An Introduction to PL/SQL In the following example, the areas of circles are calculated based on Radius values ranging from through 7, inclusive declare pi constant NUMBER(9,7) := 3.1415927; radius INTEGER(5); area NUMBER(14,2); begin for radius in loop area := pi*power(radius,2); insert into AREAS values (radius, area); end loop; end; The steps involved in processing the loop are shown in the following commented listing: /* Specify the criteria for the number of loop /* executions for radius in loop /* Calculate the area using the current Radius /* value area := pi*power(radius,2); /* Insert the area and radius values into the AREAS /* table insert into AREAS values (radius, area); /* Signal the end of the loop end loop; */ */ */ */ */ */ */ Note that there is no line that says radius := radius+1; in the FOR loop Since the specification of the loop specifies for radius in loop the Radius values are already specified For each value, all of the commands within the loop are executed (these commands can include other conditional logic, such as if conditions) Once the loop has completed processing a Radius value, the limits on the for clause are checked, and either the next Radius value is used or the loop execution is complete Sample output from the FOR loop execution is shown in the following listing: select * from AREAS order by Radius; RADIUS AREA -1 3.14 P:\010Comp\Oracle8\521-1\CD\Ventura\book.vp Friday, July 19, 2002 4:13:39 PM 501 ORACLE Color profile: Generic CMYK printer profile Composite Default screen 502 Series TIGHT / Oracle9i: The Complete Reference / Loney, Koch / 222521-1 / Chapter 27 Blind Folio 27:502 Part III: PL/SQL 12.57 28.27 50.27 78.54 113.1 153.94 rows selected Cursor FOR Loops In FOR loops, the loop executes a specified number of times In a Cursor FOR loop, the results of a query are used to dynamically determine the number of times the loop is executed In a Cursor FOR loop, the opening, fetching, and closing of cursors is performed implicitly; you not need to explicitly specify these actions The following listing shows a Cursor FOR loop that queries the RADIUS_VALS table and inserts records into the AREAS table: declare pi constant NUMBER(9,7) := 3.1415927; area NUMBER(14,2); cursor rad_cursor is select * from RADIUS_VALS; begin for rad_val in rad_cursor loop area := pi*power(rad_val.radius,2); insert into AREAS values (rad_val.radius, area); end loop; end; In a Cursor FOR loop, there is no open or fetch command The command for rad_val in rad_cursor implicitly opens the rad_cursor cursor and fetches a value into the rad_val variable When no more records are in the cursor, the loop is exited and the cursor is closed In a Cursor FOR loop, there is no need for a close command Note that rad_val is not explicitly declared in the block The loop portion of the PL/SQL block is shown in the following listing, with comments to indicate the flow of control The loop is controlled by the existence of a fetchable record in the rad_cursor cursor There is no need to check the cursor’s %NOTFOUND attribute—that is automated via the Cursor FOR loop /* If a record can be fetched from the cursor, /* then fetch it into the rad_val variable If /* no rows can be fetched, then skip the loop for rad_val in rad_cursor /* Begin the loop commands loop /* Calculate the area based on the Radius value P:\010Comp\Oracle8\521-1\CD\Ventura\book.vp Friday, July 19, 2002 4:13:39 PM */ */ */ */ */ ORACLE Color profile: Generic CMYK printer profile Composite Default screen Series TIGHT / Oracle9i: The Complete Reference / Loney, Koch / 222521-1 / Chapter 27 Blind Folio 27:503 Chapter 27: An Introduction to PL/SQL /* and insert a record into the AREAS table area := pi*power(rad_val.radius,2); insert into AREAS values (rad_val.radius, area); /* Signal the end of the loop commands end loop; */ */ Sample output is shown in the following listing; for this example, the RADIUS_VALS table has three records, with Radius values of 3, 4, and 10: select * from RADIUS_VALS order by Radius; RADIUS -3 10 The execution of the PL/SQL block with the Cursor FOR loop will generate the following records in the AREAS table: select * from AREAS order by Radius; RADIUS AREA -3 28.27 50.27 10 314.16 WHILE Loops In a WHILE loop, the loop is processed until an exit condition is met Instead of specifying the exit condition via an exit command within the loop, the exit condition is specified in the while command that initiates the loop In the following listing, a WHILE loop is created so that multiple Radius values will be processed If the current value of the Radius variable meets the while condition in the loop’s specification, then the loop’s commands are processed Once a Radius value fails the while condition in the loop’s specification, the loop’s execution is terminated: declare pi constant NUMBER(9,7) := 3.1415927; radius INTEGER(5); area NUMBER(14,2); begin radius := 3; while radius

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

Từ khóa liên quan

Mục lục

  • PART II - SQL and SQL*PLUS

    • Chapter 21 - Using SQL*Loader to Load Data 393

      • Managing Data Loads 402

        • Repeating Data Loads 403

        • Tuning Data Loads 404

          • Direct Path Loading 405

          • Additional Oracle9i Enhancements 406

          • Chapter 22 - Accessing Remote Data 409

            • Database Links 410

              • How a Database Link Works 410

              • Using a Database Link for Remote Queries 411

              • Using a Database Link for Synonyms and Views 412

              • Using a Database Link for Remote Updates 413

              • Syntax for Database Links 414

              • Using Synonyms for Location Transparency 417

              • Using the User Pseudo-column in Views 418

              • Dynamic Links: Using the SQLPLUS copy Command 420

              • Connecting to a Remote Database 421

              • Chapter 23 - Using Materialized Views 423

                • Functionality 424

                • Required System Privileges 424

                • Required Table Privileges 425

                • Read-Only vs. Updatable 425

                • create materialized view Syntax 426

                  • RowID vs. Primary Key-Based Materialized Views 430

                  • Underlying Objects Created 430

                  • Using Materialized Views to Alter Query Execution Paths 431

                  • Refreshing Materialized Views 432

                    • What Kind of Refreshes Can Be Performed? 432

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan