OCA/OCP Oracle Database 11g All-in-One Exam Guide 336 be committed in a fraction of a second. Because LGWR writes in very nearly real time, virtually all the transaction’s changes are on disk already. When you say COMMIT, LGWR actually does write in real time: your session will hang until the write is complete. This delay will be the length of time it takes to flush the last bit of redo from the log buffer to disk, which will take milliseconds. Your session is then free to continue, and from then on all other sessions will no longer be redirected to the undo blocks when they address the changed table, unless the principle of consistency requires it. The change vectors written to the redo log are all the change vectors: those applied to data blocks (tables and indexes) and those applied to undo segments. EXAM TIP The redo log stream includes all changes: those applied to data segments and to undo segments, for both committed and uncommitted transactions. Where there is often confusion is that the stream of redo written out to the log files by LGWR will contain changes for both committed and uncommitted transactions. Furthermore, at any given moment DBWn may or may not have written out changed blocks of data segments or undo segments to the datafiles for both committed and uncommitted transactions. So in principle, your database on disk is corrupted: the datafiles may well be storing uncommitted work, and be missing committed changes. But in the event of a crash, the stream of redo on disk always has enough information to reinstantiate any committed transactions that are not in the datafiles (by use of the changes applied to data blocks), and to reinstantiate the undo segments (by use of the changes applied to undo blocks) needed to roll back any uncommitted transactions that are in the datafiles. EXAM TIP Any DDL command, or a GRANT or REVOKE, will commit the current transaction. ROLLBACK While a transaction is in progress, Oracle keeps an image of the data as it was before the transaction. This image is presented to other sessions that query the data while the transaction is in progress. It is also used to roll back the transaction automatically if anything goes wrong, or deliberately if the session requests it. The syntax to request a rollback is as follows: ROLLBACK [TO SAVEPOINT savepoint] ; The optional use of savepoints is detailed in the section following. The state of the data before the rollback is that the data has been changed, but the information needed to reverse the changes is available. This information is presented to all other sessions, in order to implement the principle of isolation. The rollback will discard all the changes by restoring the prechange image of the data; any rows the transaction inserted will be deleted, any rows the transaction deleted will be inserted Chapter 8: DML and Concurrency 337 PART II back into the table, and any rows that were updated will be returned to their original state. Other sessions will not be aware that anything has happened at all; they never saw the changes. The session that did the transaction will now see the data as it was before the transaction started. SAVEPOINT Savepoints allow a programmer to set a marker in a transaction that can be used to control the effect of the ROLLBACK command. Rather than rolling back the whole transaction and terminating it, it becomes possible to reverse all changes made after a particular point but leave changes made before that point intact. The transaction itself remains in progress: still uncommitted, still able to be rolled back, and still invisible to other sessions. The syntax is as follows: SAVEPOINT savepoint; This creates a named point in the transaction that can be used in a subsequent ROLLBACK command. The following table illustrates the number of rows in a table at various stages in a transaction. The table is a very simple table called TAB, with one column. Command Rows Visible to the User Rows Visible to Others truncate table tab; 00 insert into tab values ('one'); 10 savepoint first; 10 insert into tab values ('two'); 20 savepoint second; 20 insert into tab values ('three'); 30 rollback to savepoint second; 20 rollback to savepoint first; 10 commit; 11 delete from tab; 01 rollback; 11 The example in the table shows two transactions: the first terminated with a COMMIT, the second with a ROLLBACK. It can be seen that the use of savepoints is visible only within the transaction: other sessions see nothing that is not committed. SELECT FOR UPDATE One last transaction control statement is SELECT FOR UPDATE. Oracle, by default, provides the highest possible level of concurrency: readers do not block writers, and writers do not block readers. Or in plain language, there is no problem with one OCA/OCP Oracle Database 11g All-in-One Exam Guide 338 session querying data that another session is updating, or one session updating data that another session is querying. However, there are times when you may wish to change this behavior and prevent changes to data that is being queried. It is not unusual for an application to retrieve a set of rows with a SELECT command, present them to a user for perusal, and prompt them for any changes. Because Oracle is a multiuser database, it is not impossible that another session has also retrieved the same rows. If both sessions attempt to make changes, there can be some rather odd effects. The following table depicts such a situation. First User Second User select * from regions; select * from regions; delete from regions where region_id=5; commit; update regions set region_name='GB'where region_id=5; This is what the first user will see, from a SQL*Plus prompt: SQL> select * from regions; REGION_ID REGION_NAME 5 UK 1 Europe 2 Americas 3 Asia 4 Middle East and Africa SQL> update regions set region_name='GB' where region_id=5; 0 rows updated. This is a bit disconcerting. One way around this problem is to lock the rows in which one is interested: select * from regions for update; The FOR UPDATE clause will place a lock on all the rows retrieved. No changes can be made to them by any session other than that which issued the command, and therefore the subsequent updates will succeed: it is not possible for the rows to have been changed. This means that one session will have a consistent view of the data (it won’t change), but the price to be paid is that other sessions will hang if they try to update any of the locked rows (they can, of course, query them). The locks placed by a FOR UPDATE clause will be held until the session issuing the command issues a COMMIT or ROLLBACK. This must be done to release the locks, even if no DML commands have been executed. The So-Called “Autocommit” To conclude this discussion of commit processing, it is necessary to remove any confusion about what is often called autocommit, or sometimes implicit commit. You Chapter 8: DML and Concurrency 339 PART II will often hear it said that in some situations Oracle will autocommit. One of these situations is when doing DDL, which is described in the preceding section; another is when you exit from a user process such as SQL*Plus. Quite simply, there is no such thing as an automatic commit. When you execute a DDL statement, there is a perfectly normal COMMIT included in the source code that implements the DDL command. But what about when you exit from your user process? If you are using SQL*Plus on a Windows terminal and you issue a DML statement followed by an EXIT, your transaction will be committed. This is because built into the SQL*Plus EXIT command there is a COMMIT statement. But what if you click in the top-right corner of the SQL*Plus window? The window will close, and if you log in again, you will see that the transaction has been rolled back. This is because the programmers who wrote SQL*Plus for Microsoft Windows included a ROLLBACK statement in the code that is executed when you close the window. The behavior of SQL*Plus on other platforms may well be different; the only way to be sure is to test it. So whether you get an “autocommit” when you exit from a program in various ways is entirely dependent on how your programmers wrote your user process. The Oracle server will simply do what it is told to do. There is a SQL*Plus command SET AUTOCOMMIT ON. This will cause SQL*Plus to modify its behavior: it will append a COMMIT to every DML statement issued. So all statements are committed immediately as soon as they are executed and cannot be rolled back. But this is happening purely on the user process side; there is still no autocommit in the database, and the changes made by a long-running statement will be isolated from other sessions until the statement completes. Of course, a disorderly exit from SQL*Plus in these circumstances, such as killing it with an operating system utility while the statement is running, will be detected by PMON and the active transaction will always be rolled back. Exercise 8-4: Manage Data Using DML In this exercise, you will demonstrate transaction isolation and control. Use two SQL*Plus sessions (or SQL Developer if you prefer), each connected as user SYSTEM. Run the commands in the steps that follow in the two sessions in the correct order. Step In Your First Session In Your Second Session 1 create table t1 as select * from all_users; 2 select count(*) from t1; select count(*) from t1; Results are the same in both sessions. 3 delete from t1; 4 select count(*) from t1; select count(*) from t1; Results differ because transaction isolation conceals the changes. 5 rollback; 6 select count(*) from t1; select count(*) from t1; OCA/OCP Oracle Database 11g All-in-One Exam Guide 340 Results are the same in both sessions. 7 delete from t1; 8 select count(*) from t1; select count(*) from t1; 9 create view v1 as select * from t1; 10 select count(*) from t1; select count(*) from t1; 11 rollback; 12 select count(*) from t1; select count(*) from t1; Oh dear! The DDL statement committed the DELETE, so it can’t be rolled back. 13 drop view v1; 14 drop table t1; Identify and Administer PL/SQL Objects PL/SQL is Oracle’s proprietary third-generation language that runs within the database. You can use it to retrieve and manipulate data with SQL, while using procedural constructs such as IF . . . THEN . . . ELSE or FOR or WHILE. The PL/SQL code can be stored on a client machine and sent to the server for execution, or it can be stored within the database as a named block of code. EXAM TIP PL/SQL always executes within the database, no matter where it is stored. Java can run either within the database or on the user machine. Stored and Anonymous PL/SQL PL/SQL runs within the database, but it can be stored on either the client or the server. PL/SQL code can also be entered interactively from a SQL*Plus prompt. Stored PL/SQL is loaded into the database and stored within the data dictionary as a named PL/SQL object. When it is saved to the database, it is compiled: the compilation process checks for syntactical errors and also picks up errors relating to the data objects the code addresses. This saves time when the code is actually run, and means that programmers should pick up errors at compilation time, before users encounter them. Code stored remotely, or ad hoc code issued at the SQL*Plus prompt, is called anonymous PL/SQL. It is compiled dynamically; which impacts on performance, and it also raises the possibility that unexpected errors might occur. Figure 8-5 shows an example of running an anonymous PL/SQL block and of creating and running a stored procedure. The anonymous block in Figure 8-5 creates a variable called INCREASE with the DECLARE statement and sets it to 10. Then the procedural code (within the BEGIN . . . Chapter 8: DML and Concurrency 341 PART II END statements) uses the variable within a SQL statement that updates a column of a table. The second example in the figure creates a procedure called INC_SAL, stored within the data dictionary. It takes a numeric argument called INCREASE and uses this in a SQL UPDATE statement. Then the procedure is invoked with the EXECUTE command, passing in a value for the argument. These examples are very simple, but they should illustrate how anonymous PL/SQL runs just once and therefore must be compiled at execution time, whereas stored PL/SQL can be compiled in advance and then executed many times. PL/SQL Objects There are six commonly used types of PL/SQL objects: Procedure, Function, Package, Package body, Trigger, and Type body. All are schema objects stored within the data dictionary. Procedures and functions are subprograms usually intended for performing repetitive instructions. Packages are collections of procedures and functions, grouped together for manageability. Triggers cannot be packaged: they are associated with tables and run whenever an appropriate DML statement is executed against the tables. Object types are beyond the scope of the OCP examinations. TIP SQL*Plus and Database Control are only suitable for small-scale PL/SQL development. For real work, your programmers will need a proper IDE (integrated development environment) tool that will assist with syntax checking, debugging, and source code management. Procedures and Functions A procedure is a block of code that carries out some action. It can, optionally, be defined with a number of arguments. These arguments are replaced with the actual parameters given when the procedure is invoked. The arguments can be IN arguments, Figure 8-5 Anonymous and stored PL/SQL OCA/OCP Oracle Database 11g All-in-One Exam Guide 342 meaning that they are used to pass data into the procedure, or OUT arguments, meaning that they are modified by the procedure and after execution the new values are passed out of the procedure. Arguments can also be IN-OUT, where the one variable serves both purposes. Within a procedure, you can define any number of variables that, unlike the arguments, are private to the procedure. To run a procedure, either call it from within a PL/SQL block or use the interactive EXECUTE command. A function is similar in concept to a procedure, but it does not have OUT arguments and cannot be invoked with EXECUTE. It returns a single value, with the RETURN statement. Anything that a function can do, a procedure could do also. Functions are generally used for relatively simple operations: small code blocks that will be used many times. Procedures are more commonly used to divide code into modules, and may contain long and complex processes. Packages To group related procedures and functions together, your programmers create packages. A package consists of two objects: a specification and a body. A package specification lists the functions and procedures in the package, with their call specifications: the arguments and their data types. It can also define variables and constants accessible to all the procedures and functions in the package. The package body contains the PL/SQL code that implements the package: the code that creates the procedures and functions. To create a package specification, use the CREATE PACKAGE command. For example, SQL> create or replace package numbers 2 as 3 function odd_even(v1 number) return varchar2; 4 procedure ins_ints(v1 in number); 5 end numbers; 6 / Package created. Then to create the package body, use the CREATE OR REPLACE PACKAGE BODY statement to create the individual functions and procedures. There are several hundred PL/SQL packages provided as standard with the Oracle database. These supplied packages are, for the most part, created when you create a database. To invoke a packaged procedure, you must prefix the procedure name with the package name. For example, SQL> exec numbers.odd_even(5); This will run the ODD_EVEN procedure in the NUMBERS package. The package must exist in the schema to which the user is connected, or it would be necessary to prefix the package name with the schema name. The user would also need to have the EXECUTE privilege on the package. Database Triggers Database triggers are a special category of PL/SQL object, in that they cannot be invoked manually. A trigger runs (or “fires”) automatically, when a particular action is carried Chapter 8: DML and Concurrency 343 PART II out, or when a certain situation arises; this is the triggering event. There are a number of possible triggering events. For many of them the trigger can be configured to fire either before or after the event. It is also possible to have both before and after triggers defined for the same event. The DML triggers, that fire when rows are inserted, updated, or deleted, can be configured to fire once for each affected row, or once per statement execution. All triggers have one factor in common: their execution is completely beyond the control of the user who caused the triggering event. The user may not even know that the trigger fired. This makes triggers admirably suited to auditing user actions and implementing security. The following table describes the commonly used triggering events. Event Before or After? DML triggers: INSERT UPDATE DELETE Before and/or after Can fire once per statement, or once per row. A MERGE command will fire whatever triggers are appropriate to the action carried out. DDL triggers: CREATE ALTER DROP TRUNCATE Before and/or after Database operations: SERVERERROR LOGON LOGOFF STARTUP SHUTDOWN After After Before After Before SUSPEND After Fires after a resumable operation is suspended because of a space error. Note that there is no such thing as a trigger on SELECT, though Chapter 6 showed how fine-grained auditing can be used to produce a similar effect. There are numerous uses for triggers. These might include: • Auditing users’ actions A trigger can capture full details of what was done and who did it, and write them out to an audit table. • Executing complex edits An action on one row may, in business terms, require a number of associated actions on other tables. The trigger can perform these automatically. • Security A trigger can check the time, the user’s IP address, the program they are running, and any other factors that should limit what the session can do. • Enforcing complex constraints An action may be fine in terms of the constraints on one table but may need to be validated against the contents of several other tables. OCA/OCP Oracle Database 11g All-in-One Exam Guide 344 EXAM TIP It is impossible to run a trigger by any means other than its triggering event. Exercise 8-5: Create PL/SQL Objects In this exercise, you will use Database Control to create PL/SQL objects, and execute them with SQL*Plus. 1. Connect to your database as user SYSTEM with SQL*Plus. 2. Create a table to be used for this exercise: create table integers(c1 number, c2 varchar2(5)); 3. Connect to your database as user SYSTEM with Database Control. 4. From the database home page, take the Schema tab and then the Packages link in the Programs section. Click CREATE. 5. In the Create Package window, enter NUMBERS as the package name, and the source code for the package as shown in the next illustration. Click OK to create the package. 6. From the database home page, take the Schema tab and then the Packages Bodies link in the Programs section. Click CREATE. 7. In the Create Package Body window, enter NUMBERS as the package name, and the source code for the package body as in the next illustration. Click OK to create the package body. Chapter 8: DML and Concurrency 345 PART II 8. In your SQL*Plus session, describe the package, execute the procedure, and check the results, as in this illustration: 9. Tidy up by dropping the package and table: drop package numbers; drop table integers; Note that this first DROP will COMMIT the insert of the rows. . OCA/ OCP Oracle Database 11g All-in-One Exam Guide 336 be committed in a fraction of a second. Because LGWR writes in very nearly real time, virtually all the transaction’s changes are on. 8-5 Anonymous and stored PL/SQL OCA/ OCP Oracle Database 11g All-in-One Exam Guide 342 meaning that they are used to pass data into the procedure, or OUT arguments, meaning that they are modified. OCA/ OCP Oracle Database 11g All-in-One Exam Guide 338 session querying data that another session is updating, or one session updating data that another session is querying. However, there are