目录
一、实验目的
1.掌握PL/SQL的块结构及基本语法。
2.掌握使用常量和变量的方法。
3. 熟悉表达式和函数的使用。
4.掌握PL/SQL的控制结构与语句应用。
5.熟悉PL/SQL中的异常处理方法。
二、实验内容
1.PL/SQL块结构和基本语法要求
- 块(BLOCK)
PL/SQL程序的基本单元是块(BLOCK),块就是实现一定功能的逻辑模块。一个PL/SQL程序由一个或多个块组成。块有固定的结构,也可以嵌套。一个块可以包括声明部分、执行部分、异常处理部分,结构如下:
DECLARE -- 声明块
-- 声明一些变量、常量、用户定义的数据类型以及游标等
-- 这一部分可选,如不需要可以不写
BEGIN -- 执行块
-- 程序主体
EXCEPTION --异常块
-- 异常处理程序,当程序出错误时执行
END;
-- 程序结束
- 结果输出
PL/SQL使用函数DBMS_OUTPUT.PUT_LINE显示输出结果。DBMS_OUTPUT是Oracle提供的包,该包有如下三个用于输出的函数,用于显示PL/SQL程序模块的输出信息。
① 用于输出字符串,但不换行。语法如下:
DBMS_OUTPUT.PUT(字符串表达式);
② 用于输出一行字符串信息,并换行。语法如下:
DBMS_OUTPUT.PUT_LINE(字符串表达式);
③ 用来输出一个换行,没有参数。语法如下:
DBMS_OUTPUT.NEW_LINE;
要使用DBMS_OUTPUT.PUT_LINE函数显示输出数据,在SQL*Plus环境下要先执行一次如下的环境设置命令:
SET SERVEROUTPUT ON [SIZE n]
用来打开DBMS_OUTPUT.PUT_LINE函数的屏幕输出功能,系统默认状态是OFF。其中,n表示输出缓冲区的大小。n的范围在2000~1 000 000之间,默认为2000。如果输出内容较多,需要使用SIZE n来设置较大的输出缓冲区。
- 使用SELECT语句查询
在PL/SQL程序中,最常见的是使用SELECT语句从数据库中获取信息。但是,同直接执行SELECT语句不同,在PL/SQL模块中的SELECT语句总是和INTO相配合,INTO后跟用于接收查询结果的变量,形式如下:
SELECT 列名1,列名2...
INTO 变量1,变量2...
FROM 表名
WHERE 条件;
注意:接收查询结果的变量类型、顺序和个数同SELECT语句的字段的类型、顺序和个数应该完全一致。并且SELECT语句返回的数据必须是一行,否则将引发系统错误。
当程序要接收返回的多行结果时,可以采用后面介绍的游标的方法。
在“XXX数据库”中,按下列要求完成查询:
- 查询每个货品的销售情况,包括:货品编码、货品名称、销售数量及销售总价。
DECLARE
v_code product.code%TYPE;
v_name product.name%TYPE;
v_quantity orders.quantity%TYPE;
v_price_sum NUMBER;
BEGIN
SELECT product.code,product.name,orders.quantity,product.price*quantity
INTO v_code,v_name,v_quantity,v_price_sum
FROM product join orders on product.code = orders.product_code
WHERE product.code = 2;
DBMS_OUTPUT.PUT_LINE('货品编码:'||v_code);
DBMS_OUTPUT.PUT_LINE('货品名称:'||v_name);
DBMS_OUTPUT.PUT_LINE('销售数量:'||v_quantity);
DBMS_OUTPUT.PUT_LINE('销售总价:'||v_price_sum);
END;
SET SERVEROUTPUT ON
2.使用数据操纵语句
使用INSERT、DELETE和UPDATE的语法没有变化,但在程序中要注意判断语句执行的状态,并使用COMMIT或ROLLBACK进行事务处理。
- 为“XXX数据库”添加新客户。若客户已经存在,则输出提示信息“客户XX已存在!”。插入成功,提示信息“XX客户已成功添加!”
DECLARE
v_code customer.code%TYPE := 12;
v_name customer.name%TYPE := '小刘';
v_address customer.address%TYPE :='湖南长沙';
v_phone customer.phone%TYPE := 1234567897;
BEGIN
BEGIN
SELECT code INTO v_code FROM customer WHERE name = v_name;
DBMS_OUTPUT.PUT_LINE('客户' || v_name || '已存在!');
EXCEPTION
WHEN NO_DATA_FOUND THEN
INSERT INTO customer ( code,name, address, phone) VALUES (v_code,v_name, v_address, v_phone);
DBMS_OUTPUT.PUT_LINE(v_name || '客户已成功添加!');
END;
END;
- 按销售情况,修改“货品信息表”的库存量,并给出提示。
DECLARE
v_code product.code%TYPE := 2;
v_name product.name%TYPE;
v_inventory product.inventory%TYPE;
v_quantity NUMBER := 1;
BEGIN
UPDATE product SET inventory=inventory-v_quantity WHERE code = v_code;
DBMS_OUTPUT.PUT_LINE('货品编码:'||v_code);
DBMS_OUTPUT.PUT_LINE('库存量:'||v_inventory);
END;
SELECT * from product;
3.PL/SQL的控制语句
- IF条件
(4)在(3)基础上使用IF条件完善数据更新操作。在修改货品库存时,如果货品的库存不足(库存量≤0)时,修改货品状态为0,并提示 “货品库存不足,请及时补货!”。
DECLARE
v_code product.code%TYPE := 2;
v_name product.name%TYPE;
v_inventory product.inventory%TYPE;
v_quantity NUMBER := 1;
BEGIN
UPDATE product SET inventory = inventory - v_quantity WHERE code = v_code;
SELECT inventory INTO v_inventory FROM product WHERE code = v_code; -- 查询库存量
DBMS_OUTPUT.PUT_LINE('货品编码:' || v_code);
IF v_inventory > 0 THEN
DBMS_OUTPUT.PUT_LINE('库存量:' || v_inventory);
ELSE
UPDATE product SET status = 0 WHERE code = v_code; -- 修改货品状态为0
DBMS_OUTPUT.PUT_LINE('货品库存不足,请及时补货!');
END IF;
END;
(5)我国今年南方多地气温高于以往,高温警报频频。试编写一段程序用于判断当前温度是否已达高温预警,并给出相应的预警信号。高温预警信号按颜色分为黄色、橙色、红色,具体如下:
① 高温黄色预警信号:24小时内最高气温将接近或达到35℃或已达到35℃以上。
② 高温橙色预警信号:24小时内最高气温将要升至37℃以上。
③ 高温红色预警信号:24小时内最高气温将要升到39℃以上。
DECLARE
v_temp NUMBER := 36;
BEGIN
IF v_temp >= 35 THEN
DBMS_OUTPUT.PUT_LINE('高温黄色预警信号');
END IF;
IF v_temp >= 37 THEN
DBMS_OUTPUT.PUT_LINE('高温橙色预警信号');
END IF;
IF v_temp >= 39 THEN
DBMS_OUTPUT.PUT_LINE('高温红色预警信号');
END IF;
END;
1.CASE条件
(6)为“销售人员信息表”添加工资字段,并输入工资。编写程序判断销售人员的工资等级,月收入2万元以上为高收入,8000元以上为中等收入,低于8000元为低收入。
ALTER TABLE salesperson ADD salary NUMBER(10, 2);
UPDATE salesperson SET salary = 10000 WHERE employee_id = 1;
DECLARE
v_name salesperson.name%TYPE;
v_level VARCHAR2(50);
BEGIN
SELECT name,
CASE
WHEN salary >= 20000 THEN '高收入'
WHEN salary >= 8000 AND salary < 20000 THEN '中等收入'
ELSE '低收入'
END
INTO v_name, v_level
FROM salesperson
WHERE employee_id = 1;
DBMS_OUTPUT.PUT_LINE(v_name || ' 的工资等级为:' || v_level);
END;
(7)找出每个销售人员所在部门,并按“XX是YY部门的员工”格式显示在屏幕上。
DECLARE
v_department_name department.name%TYPE;
BEGIN
FOR salesperson_rec IN (SELECT name, department_id FROM salesperson)
LOOP
SELECT name INTO v_department_name
FROM department
WHERE department_id = salesperson_rec.department_id;
DBMS_OUTPUT.PUT_LINE(salesperson_rec.name || '是' || v_department_name || '部门的员工');
END LOOP;
END;
2.LOOP循环
(8)输出一个空心三角形。
DECLARE
v_max_rows CONSTANT NUMBER := 9;
BEGIN
dbms_output.put_line(' ');
FOR i IN 1..v_max_rows LOOP
FOR j IN 1..(v_max_rows-i) LOOP
DBMS_OUTPUT.PUT(' ');
END LOOP;
FOR k IN 1..(2*i-1) LOOP
IF k = 1 OR k = (2*i-1) OR i = v_max_rows THEN
DBMS_OUTPUT.PUT('*');
ELSE
DBMS_OUTPUT.PUT(' ');
END IF;
END LOOP;
DBMS_OUTPUT.NEW_LINE;
END LOOP;
END;
(9)求1!+2!+...+10!的值。
declare
sum_num number(8) :=0;
n number(8) :=1;
begin
for i in 1..10 loop
n:=n*i;
sum_num:=sum_num +n;
end loop;
dbms_output.put_line('结果为' || sum_num);
end;
(10)使用WHILE LOOP循环向“订单信息表”中连续插入5条记录。
DECLARE
v_counter NUMBER := 10;
BEGIN
WHILE v_counter <= 15 LOOP
INSERT INTO orders (order_id, employee_id, product_code, customer_code, quantity, order_date)
VALUES (v_counter, 1, 1, 1, 1, SYSDATE);
v_counter := v_counter + 1;
END LOOP;
END;
SELECT * FROM orders;