友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
SQL 21日自学通(V3.0)(PDF格式)-第51部分
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!
激活
394
…………………………………………………………Page 395……………………………………………………………
SQL 21 日自学通(V1。0) 翻译人 笨猪
如果在这个语句块运行的过程中产生的异常 用户将会看到
INPUT
SQL》 @block1
ERROR: DIVISOR IS ZERO。 SEE YOUR DBA。
PL/SQL procedure successfully pleted。
是不是这样的错误信息比下边的错误信息更友好
输入/输出
SQL》 @block1
begin
*
ERROR at line 1:
ORA…01476: divisor is equal to zero
ORA…06512: at line 20
在 PL/SQL 中的事务控制
在第 11 天中的 事务控制 中 我们已经讨论了事务控制命令 MIT ROLLBACK
SAVEPOINT 这些命令可以让程序员在在事务向数据库中进行写操作时加以控制 在多数
时候所进行的操作是需要撤消
语法
BEGIN
DECLARE
。。。
BEGIN
statements。。。
IF condition THEN
MIT;
ELSE
ROLLBACK;
END IF;
395
…………………………………………………………Page 396……………………………………………………………
SQL 21 日自学通(V1。0) 翻译人 笨猪
。。。
EXCEPTION
。。。
END;
END;
PL/SQL 的一个好处就是你可以用自动地执行事务控制命令来代替对大型事务的不断
监控— — 这是非常单调和乏味的
让所有的事在一起工作
到目前为止 我们已经介绍了 PL/SQL 你已经熟悉了它所支持的数据类型以及 PL/SQL
语句块的主要特性 你已经知道了如何定义一个局部变量 常量和指针 你也已经知道了
如何在一个 PROCDURE 部分 指针的操作部分和异常部分嵌入 SQL 语句 当指针在使用
时 你应该清楚地知道如何在异常部分捕获它 现在你已经可以使用 BEGIN END 语
句块来进行了实际工作 在今天的结束部分 你将会彻底明白 PL/SQL 语句块之间的相同
关系
示例表及数据
在我们创建的 PL/SQL 语句块中使用两个表 PAYMENT_TABLE 确定了一个客户 她
/他的付款是多少 应得的总数是多少 PAY_STATUS_TABLE 最初实际上没有任何数据
数据将会依据 PAYMENT_TABLE 中的特定条件插入到 PAY_STATUS_TABLE 表中
输入
SQL》 select * from payment_table;
输出
CUSTOMER PAYMENT TOTAL_DUE
ABC 90。50 150。99
AAA 79。00 79。00
BBB 950。00 1000。00
CCC 27。50 27。50
DDD 350。00 500。95
EEE 67。89 67。89
396
…………………………………………………………Page 397……………………………………………………………
SQL 21 日自学通(V1。0) 翻译人 笨猪
FFF 555。55 455。55
GGG 122。36 122。36
HHH 26。75 0。00
输入
SQL》 describe pay_status_table
输出
Name Null? Type
CUST_ID NOT NULL CHAR(3)
STATUS NOT NULL VARCHAR2(15)
AMT_OWED NUMBER(8;2)
AMT_CREDIT NUMBER(8;2)
分析
DESCRIBE 是一个 ORACLE SQL 它可以不通过查询数据字典就可以显示一个表的结
构 它与其它的 ORACLE SQL*PLUS 命令将会在第 20 天 SQL*PLUS 中提到
一个简单的 PL/SQL 语句块
这个 PL/SQL 的脚本内容如下所示
输入
set serveroutput on
BEGIN
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
397
…………………………………………………………Page 398……………………………………………………………
SQL 21 日自学通(V1。0) 翻译人 笨猪
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 》 fTotalDue ) then
fOverPaid := fPayment fTotalDue;
insert into pay_status_table (cust_id; status; amt_credit)
values (cCustId; 'Over Paid'; fOverPaid);
elsif ( fPayment 《 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;
/
398
…………………………………………………………Page 399……………………………………………………………
SQL 21 日自学通(V1。0) 翻译人 笨猪
分析
DECLARE 部分定义了六个局部变量 与被称为payment_cursor 指针一样 PROCEDURE
从第二个 BEGIN 语句开始并先打开了这个游标并开始循环 而 FETCH 命令则将当前指针
所指向的记录的内容存入在 DECLARE 部分定义的变量中 当在指针中发现记录以后 语
句会将客户的支付与他应付的总数进行比较 根据支付的的数量来计算已付款的人数和未
付款的人数 然后将计算过的数据插入到 PAY_STATUS_TABLE 表中 当循环终止以后
关闭指针 异常用于处理在这一部分可以发生的错误
现在 我们来运行一个这个脚本看一个他的结果
INPUT:
SQL》 @block1
OUTPUT:
Input truncated to 1 characters
ERROR: amount is Zero。 See your supervisor。
PL/SQL procedure successfully pleted。
现在看来你在应得总数上有一个数值是不正确的 你应该修正这个数量然后再运行脚
本
输入/输出
SQL》 update payment_table set total_due = 26。75 where cust_id = 'HHH';
1 row updated。
SQL》 mit;
mit plete。
SQL》 truncate table pay_status_table;
Table truncated。
注 在上例中我们清除了 pay_status_table 中的内容 在下一次运行这个语句块时表将会被
重新写入 你也许会想把清除语句也加入到语句块中吧
输入/输出
SQL》 @block1
Input truncated to 1 characters
PL/SQL procedure successfully pleted。
399
…………………………………………………………Page 400……………………………………………………………
SQL 21 日自学通(V1。0) 翻译人 笨猪
现在你可以对 PAY_STATUS_TABLE 表执行 SELECT 语句 看一下每一个客户的支付
情况
输入/输出
SQL》 select * from pay_status_table order by status;
CUSTOMER STATUS AMT_OWED AMT_CREDIT
FFF OverPaid 100。00
AAA PaidinFull
CCC PaidinFull
EEE PaidinFull
GGG PaidinFull
HHH PaidinFull
ABC StillOwes 60。49
DDD StillOwes 150。95
BBB StillOwes 50。00
分析
从 PAYMENT_TABLE 获得的数据中有一行被插入到了 PAY_STATUS_TABLE 表中
如果用户的付款金额比应付金额更多 那么差额将会被输入到 AMT_CREDIT 列中 如果
用户的支付金额少于应付金额 那么将会在 AMT_OWED 中输入一个信息 如果客户已经
全部支付完毕 那么这两列中就不会有任何数据
又一个程序
在这个例子中使用的表叫 PAY_TABLE
输入
SQL》 desc pay_table
输出
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)
先来看一下数据
400
…………………………………………………………Page 401……………………………………………………………
SQL 21 日自学通(V1。0) 翻译人 笨猪
输入
SQL》 select * from pay_table order by pay_type; pay_rate desc;
输出
NAME PAY_TYPE PAY_RATE EFF_DATE PREV_PAY
SANDRA SAMUELS HOURLY 12。50 01…JAN…97
ROBERT BOBAY HOURLY 11。50 15…MAY…96
KEITH JONES HOURLY 10。00 31…OCT…96
SUSAN WILLIAMS HOURLY 9。75 01…MAY…97
CHRISSY ZOES SALARY 50000。00 01…JAN…97
CLODE EVANS SALARY 42150。00 01…MAR…97
JOHN SMITH SALARY 35000。00 15…JUN…96
KEVIN TROLLBERG SALARY 27500。00 15…JUN…96
现实情况 由于销售情况很好 你需要给为你工作的时间超过了六个月的个人增加薪
金 符合条件的钟点工的薪金增加 4% 而符全条件的雇员的薪金需要增加 5%
今天的日期是
输入/输出
SQL》 select sysdate from dual
SYSDATE
20…MAY…97
在对下边的 PL/SQL 语句块进行检查之前 我们要对 PAY_TABLE 表进行手工的选择
以找出都有哪些人需要增加薪金
输入
SQL》 select name; pay_type; pay_rate; eff_date;
2 'YES' due
3 from pay_table
4 where eff_date 《 sysdate 180
5 UNION ALL
6 select name; pay_type; pay_rate; eff_date;
7 'No' due
8 from pay_table
9 where eff_date 》= sysdate 180
401
…………………………………………………………Page 402……………………………………………………………
SQL 21 日自学通(V1。0) 翻译人 笨猪
10 order by 2; 3 desc;
输出
NAME PAY_TYPE PAY_RATE EFF_DATE DUE
SANDRA SAMUELS HOURLY 12。50 01…JAN…97 No
ROBERT BOBAY HOURLY 11。50 15…MAY…96 YES
KEITH JONES HOURLY 10。00 31…OCT…96 YES
SUSAN WILLIAMS HOURLY 9。75 01…MAY…97 No
CHRISSY ZOES SALARY 50000。00 01…JAN…97 No
CLODE EVANS SALARY 42150。00 01…MAR…97 No
JOHN SMITH SALARY 35000。00 15…JUN…96 YES
KEVIN TROLLBERG SALARY 27500。00 15…JUN…96 YES
DUE 列的内容是确定每一个人是否有增加工资的资格 下边是 PL/SQL 的脚本
输入
set serveroutput on
BEGIN
DECLARE
UnknownPayType exception;
cursor pay_cursor is
select name; pay_type; pay_rate; eff_date;
sysdate; rowid
from pay_table;
IndRec pay_cursor%ROWTYPE;
cOldDate date;
fNewPay number(8;2);
BEGIN
open pay_cursor;
loop
fetch pay_cursor into IndRec;
exit when pay_cursor%NOTFOUND;
cOldDate := sysdate 180;
if (IndRec。pay_type = 'SALARY') then
402
…………………………………………………………Page 403……………………………………………………………
SQL 21 日自学通(V1。0) 翻译人 笨猪
fNewPay := IndRec。pay_rate * 1。05;
elsif (IndRec。pay_type = 'HOURLY') then
fNewPay := IndRec。pay_rate * 1。04;
else
raise UnknownPayType;
end if;
if (IndRec。eff_date 《 cOldDate) then
update pay_table
set pay_rate = fNewPay;
prev_pay = IndRec。pay_rate;
eff_date = IndRec。sysdate
where rowid = IndRec。rowid;
mit;
end if;
end loop;
close pay_cu
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!