⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch18.htm

📁 Learn SQL in an easy way...
💻 HTM
📖 第 1 页 / 共 4 页
字号:
	using the <TT>START</TT> command or the character <TT>@</TT>. PL/SQL script files	can also be called within other PL/SQL files, shell scripts, or other programs. <HR></BLOCKQUOTE><H3><FONT COLOR="#000077">Displaying Output to the User</FONT></H3><P>Particularly when handling exceptions, you may want to display output to keepusers informed about what is taking place. You can display output to convey information,and you can display your own customized error messages, which will probably makemore sense to the user than an error number. Perhaps you want the user to contactthe database administrator if an error occurs during processing, rather than to seethe exact message.</P><P>PL/SQL does not provide a direct method for displaying output as a part of itssyntax, but it does allow you to call a package that serves this function from withinthe block. The package is called <TT>DBMS_OUTPUT</TT>.</P><PRE><FONT COLOR="#0066FF">EXCEPTION  WHEN zero_divide THEN    DBMS_OUTPUT.put_line('ERROR:  DIVISOR IS ZERO.  SEE YOUR DBA.');</FONT></PRE><H5>ANALYSIS:<TT></TT></H5><P><TT>ZERO_DIVIDE</TT> is an Oracle predefined exception. Most of the common errorsthat occur during program processing will be predefined as exceptions and are raisedimplicitly (which means that you don't have to raise the error in the PROCEDURE sectionof the block).</P><P>If this exception is encountered during block processing, the user will see:</P><H5>INPUT:</H5><PRE><FONT COLOR="#0066FF">SQL&gt;<B> @block1</B>ERROR:  DIVISOR IS ZERO.  SEE YOUR DBA.PL/SQL procedure successfully completed.</FONT></PRE><P>Doesn't that message look friendly than:</P><H5>INPUT/OUTPUT:</H5><PRE><FONT COLOR="#0066FF">SQL&gt; <B>@block1begin*</B>ERROR at line 1:ORA-01476: divisor is equal to zeroORA-06512: at line 20</FONT></PRE><H2><FONT COLOR="#000077">Transactional Control in PL/SQL</FONT></H2><P>On Day 11, &quot;Controlling Transactions,&quot; we discussed the transactionalcontrol commands <TT>COMMIT</TT>, <TT>ROLLBACK</TT>, and <TT>SAVEPOINT</TT>. Thesecommands allow the programmer to control when transactions are actually written tothe database, how often, and when they should be undone.</P><H5>SYNTAX:</H5><PRE><FONT COLOR="#0066FF">BEGIN  DECLARE    ...  BEGIN    statements...    IF condition THEN      COMMIT;    ELSE      ROLLBACK;    END IF;    ...  EXCEPTION    ...  END;END;</FONT></PRE><P>The good thing about PL/SQL is that you can automate the use of transactionalcontrol commands instead of constantly monitoring large transactions, which can bevery tedious.<H2><FONT COLOR="#000077">Putting Everything Together</FONT></H2><P>So far, you have been introduced to PL/SQL, have become familiar with the supporteddata types, and are familiar with the major features of a PL/SQL block. You knowhow to declare local variables, constants, and cursors. You have also seen how toembed SQL in the <TT>PROCEDURE</TT> section, manipulate cursors, and raise exceptions.When a cursor has been raised, you should have a basic understanding of how to handleit in the <TT>EXCEPTION</TT> section of the block. Now you are ready to work withsome practical examples and create blocks from <TT>BEGIN</TT> to <TT>END</TT>. Bythe end of this section, you should fully understand how the parts of a PL/SQL blockinteract with each other.<H3><FONT COLOR="#000077">Sample Tables and Data</FONT></H3><P>We will be using two tables to create PL/SQL blocks. <TT>PAYMENT_TABLE</TT> identifiesa customer, how much he or she has paid, and the total amount due. <TT>PAY_STATUS_TABLE</TT>does not yet contain any data. Data will be inserted into <TT>PAY_STATUS_TABLE</TT>according to certain conditions in the <TT>PAYMENT_TABLE</TT>.</P><H5>INPUT:</H5><PRE><FONT COLOR="#0066FF">SQL&gt; <B>select *</B>  2  <B>from payment_table;</B></FONT></PRE><H5><FONT COLOR="#000000">OUTPUT:</FONT><FONT COLOR="#0066FF"></FONT></H5><PRE><FONT COLOR="#0066FF">CUSTOMER  PAYMENT TOTAL_DUE-------- -------- ---------ABC         90.50    150.99AAA         79.00     79.00BBB        950.00   1000.00CCC         27.50     27.50DDD        350.00    500.95EEE         67.89     67.89FFF        555.55    455.55GGG        122.36    122.36HHH         26.75      0.009 rows selected.</FONT></PRE><H5><FONT COLOR="#000000">INPUT:</FONT><FONT COLOR="#0066FF"></FONT></H5><PRE><FONT COLOR="#0066FF">SQL&gt; <B>describe pay_status_table</B></FONT></PRE><H5><FONT COLOR="#000000">OUTPUT:</FONT><FONT COLOR="#0066FF"></FONT></H5><PRE><FONT COLOR="#0066FF"> Name                            Null?    Type ------------------------------ --------- ---- CUST_ID                         NOT NULL CHAR(3) STATUS                          NOT NULL VARCHAR2(15) AMT_OWED                                 NUMBER(8,2) AMT_CREDIT                               NUMBER(8,2)</FONT></PRE><H5>ANALYSIS:<TT></TT></H5><P><TT>DESCRIBE</TT> is an Oracle SQL command that displays the structure of a tablewithout having to query the data dictionary. <TT>DESCRIBE</TT> and other Oracle SQL*Pluscommands are covered on Day 20, &quot;SQL*Plus.&quot;<H3><FONT COLOR="#000077">A Simple PL/SQL Block</FONT></H3><P>This is how the PL/SQL script (<TT>block1.sql</TT>) file looks:</P><H5>INPUT:</H5><PRE><FONT COLOR="#0066FF"><B>set serveroutput onBEGIN  DECLARE    AmtZero EXCEPTION;    cCustId payment_table.cust_id%TYPE;    fPayment payment_table.payment%TYPE;    fTotalDue payment_table.total_due%TYPE;    cursor payment_cursor is      select cust_id, payment, total_due      from payment_table;    fOverPaid number(8,2);    fUnderPaid number(8,2);  BEGIN    open payment_cursor;    loop      fetch payment_cursor into        cCustId, fPayment, fTotalDue;      exit when payment_cursor%NOTFOUND;      if ( fTotalDue = 0 ) then        raise AmtZero;      end if;      if ( fPayment &gt; fTotalDue ) then        fOverPaid := fPayment - fTotalDue;        insert into pay_status_table (cust_id, status, amt_credit)        values (cCustId, 'Over Paid', fOverPaid);      elsif ( fPayment &lt; fTotalDue ) then        fUnderPaid := fTotalDue - fPayment;        insert into pay_status_table (cust_id, status, amt_owed)        values (cCustId, 'Still Owes', fUnderPaid);      else        insert into pay_status_table        values (cCustId, 'Paid in Full', null, null);      end if;    end loop;    close payment_cursor;  EXCEPTION    when AmtZero then    DBMS_OUTPUT.put_line('ERROR: amount is Zero. See your supervisor.');    when OTHERS then    DBMS_OUTPUT.put_line('ERROR: unknown error. See the DBA');  END;END;/</B></FONT></PRE><H5>ANALYSIS:</H5><P>The <TT>DECLARE</TT> section defines six local variables, as well as a cursorcalled <TT>payment_cursor</TT>. The <TT>PROCEDURE</TT> section starts with the second<TT>BEGIN</TT> statement in which the first step is to open the cursor and starta loop. The <TT>FETCH</TT> command passes the current values in the cursor into thevariables that were defined in the <TT>DECLARE</TT> section. As long as the loopfinds records in the cursor, the statement compares the amount paid by a customerto the total amount due. Overpayments and underpayments are calculated accordingto the amount paid, and we use those calculated amounts to insert values into the<TT>PAY_STATUS_TABLE</TT>. The loop terminates, and the cursor closes. The <TT>EXCEPTION</TT>section handles errors that may occur during processing.</P><P>Now start the PL/SQL script file and see what happens.</P><H5>INPUT:</H5><PRE><FONT COLOR="#0066FF">SQL&gt;<B> @block1</B></FONT></PRE><H5><FONT COLOR="#000000">OUTPUT:</FONT><FONT COLOR="#0066FF"></FONT></H5><PRE><FONT COLOR="#0066FF">Input truncated to 1 charactersERROR: amount is Zero. See your supervisor.PL/SQL procedure successfully completed.</FONT></PRE><P>Now that you know that an incorrect amount appears in the total due column, youcan fix the amount and run the script again.</P><H5>INPUT/OUTPUT:</H5><PRE><FONT COLOR="#0066FF">SQL&gt; <B>update payment_table</B>  2  <B>set total_due = 26.75</B>  3  <B>where cust_id = 'HHH';</B>1 row updated.SQL&gt; <B>commit;</B>Commit complete.SQL&gt; <B>truncate table pay_status_table;</B>Table truncated.</FONT></PRE><BLOCKQUOTE>	<P><HR><FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>This example truncates the <TT>PAY_STATUS_TABLE</TT>	to clear the table's contents; the next run of the statement will repopulate the	table. You may want to add the <TT>TRUNCATE TABLE</TT> statement to your PL/SQL block.	<HR></P></BLOCKQUOTE><H5>INPUT/OUTPUT:</H5><PRE><FONT COLOR="#0066FF">SQL&gt; <B>@block1</B>Input truncated to 1 charactersPL/SQL procedure successfully completed.</FONT></PRE><P>Now you can select from the <TT>PAY_STATUS_TABLE</TT> and see the payment statusof each customer.</P><H5>INPUT/OUTPUT:</H5><PRE><FONT COLOR="#0066FF">SQL&gt; <B>select *</B>  2  <B>from pay_status_table</B>  3  <B>order by status;</B></FONT></PRE><PRE><FONT COLOR="#0066FF">CUSTOMER STATUS          AMT_OWED  AMT_CREDIT-------- -------------- --------- -----------FFF      Over Paid                    100.00AAA      Paid in FullCCC      Paid in FullEEE      Paid in FullGGG      Paid in FullHHH      Paid in FullABC      Still Owes         60.49DDD      Still Owes        150.95BBB      Still Owes         50.009 rows selected.</FONT></PRE><H5>ANALYSIS:</H5><P>A row was inserted into <TT>PAY_STATUS_TABLE</TT> for every row of data that iscontained in the <TT>PAYMENT_TABLE</TT>. If the customer paid more than the amountdue, then the difference was input into the <TT>amt_credit</TT> column. If the customerpaid less than the amount owed, then an entry was made in the <TT>amt_owed</TT> column.If the customer paid in full, then no dollar amount was inserted in either of thetwo columns.<H3><FONT COLOR="#000077">Another Program</FONT></H3><P>This example uses a table called <TT>PAY_TABLE</TT>:</P><H5>INPUT:</H5><PRE><FONT COLOR="#0066FF">SQL&gt; <B>desc pay_table</B></FONT></PRE><H5><FONT COLOR="#000000">OUTPUT:</FONT><FONT COLOR="#0066FF"></FONT></H5><PRE><FONT COLOR="#0066FF"> Name                            Null?    Type ------------------------------  -------- ---- NAME                            NOT NULL VARCHAR2(20) PAY_TYPE                        NOT NULL VARCHAR2(8) PAY_RATE                        NOT NULL NUMBER(8,2) EFF_DATE                        NOT NULL DATE PREV_PAY                                 NUMBER(8,2)</FONT></PRE><P>First take a look at the data:</P><H5>INPUT:</H5><PRE><FONT COLOR="#0066FF">SQL&gt; <B>select *</B>  2  <B>from pay_table</B>  3  <B>order by pay_type, pay_rate desc;</B></FONT></PRE><H5><FONT COLOR="#000000">OUTPUT:</FONT><FONT COLOR="#0066FF"></FONT></H5><PRE><FONT COLOR="#0066FF">NAME                 PAY_TYPE  PAY_RATE  EFF_DATE  PREV_PAY-------------------- -------- --------- --------- ---------SANDRA SAMUELS       HOURLY       12.50 01-JAN-97ROBERT BOBAY         HOURLY       11.50 15-MAY-96KEITH JONES          HOURLY       10.00 31-OCT-96SUSAN WILLIAMS       HOURLY        9.75 01-MAY-97CHRISSY ZOES         SALARY    50000.00 01-JAN-97CLODE EVANS          SALARY    42150.00 01-MAR-97JOHN SMITH           SALARY    35000.00 15-JUN-96KEVIN TROLLBERG      SALARY    27500.00 15-JUN-968 rows selected.</FONT></PRE><P>Situation: Sales are up. Any individual who has not had a pay increase for sixmonths (180 days) will receive a raise effective today. All eligible hourly employeeswill receive a 4 percent increase, and eligible salary employees will receive a 5percent increase.</P><P>Today is:</P><H5>INPUT/OUTPUT:</H5><PRE><FONT COLOR="#0066FF">SQL&gt; <B>select sysdate</B>  2  <B>from dual;</B>SYSDATE--------20-MAY-97</FONT></PRE><P>Before examining the next PL/SQL block, we will perform a manual select from the<TT>PAY_TABLE</TT> that flags individuals who should receive a raise.</P><H5>INPUT:</H5><PRE><FONT COLOR="#0066FF">SQL&gt; <B>select name, pay_type, pay_rate, eff_date,</B>  2         <B>'YES' due</B>  3 <B> from pay_table</B>  4  <B>where eff_date &lt; sysdate - 180</B>  5  <B>UNION ALL</B>  6  <B>select name, pay_type, pay_rate, eff_date,</B>  7       <B>  'No' due</B>  8  <B>from pay_table</B>  9  <B>where eff_date &gt;= sysdate - 180</B> 10  <B>order by 2, 3 desc;</B></FONT></PRE><H5><FONT COLOR="#000000">OUTPUT:</FONT><FONT COLOR="#0066FF"></FONT></H5><PRE><FONT COLOR="#0066FF">NAME                 PAY_TYPE  PAY_RATE EFF_DATE  DUE-------------------- --------- -------- --------- ---SANDRA SAMUELS       HOURLY       12.50 01-JAN-97 NoROBERT BOBAY         HOURLY       11.50 15-MAY-96 YESKEITH JONES          HOURLY       10.00 31-OCT-96 YESSUSAN WILLIAMS       HOURLY        9.75 01-MAY-97 NoCHRISSY ZOES         SALARY    50000.00 01-JAN-97 NoCLODE EVANS          SALARY    42150.00 01-MAR-97 NoJOHN SMITH           SALARY    35000.00 15-JUN-96 YESKEVIN TROLLBERG      SALARY    27500.00 15-JUN-96 YES8 rows selected.</FONT></PRE><P>The <TT>DUE</TT> column identifies individuals who should be eligible for a raise.Here's the PL/SQL script:</P><H5>INPUT:</H5><PRE><FONT COLOR="#0066FF"><B>set serveroutput onBEGIN  DECLARE    UnknownPayType exception;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -