概述:

PL/SQL(Procedural Language/SQL)是一种 Oracle数据库特有的、支持应用开发的语言,是Oracle在标准SQL语言上进行过程性扩展后形成的程序设计语言。

  • PL/SQL Oracle 对 SQL 过程化扩展。
  • PL/SQL 数据库编程
  • 好处:简单、高效、灵活和实用

1、语法

  • 基本语法:
-- 基本语法,(declare、exception可省略)
declare
   -- 声明,定义变量
begin
   -- 代码
   exception
     --异常处理
end;
  • 实例:实例1,定义变量i,并赋值'你好',输出
declare
 i varchar2(20);
begin
  i := '你好';
  dbms_output.put_line('输出内容是:' || i);
end;

postgre循环执行sql_postgre循环执行sql

2、入门案例

-- PL/SQL 入门练习1:打印“welcome !!!”
begin
  dbms_output.put_line('welcome !!!');
end;

-- PL/SQL 入门练习2:定义变量 v_i ,并赋值 “welcome !!!”,再打印变量
-- 变量的类型,一定要支持赋值内容长度
declare 
 v_i varchar2(40);
begin
    v_i := 'welcome welcome !!!';
    dbms_output.put_line(v_i);
end;

3、赋值+类型

3.1、赋值 into

  • 练习1:打印业主名称
-- 练习1:打印业主名称
declare
   -- 声明变量,用于存放name的值
begin
   -- 执行查询语句,获得name的值,并赋值变量
   -- 打印变量
end;
  • 实现
-- 练习1:打印业主名称
declare
   -- 声明变量,用于存放name的值
   v_name varchar2(50);
begin
   -- 执行查询语句,获得name的值,并赋值变量
   select name into v_name from t_owners where id = 11;
   -- 打印变量
   dbms_output.put_line(v_name);
end;

3.2、变量类型 %type

  • 练习2:打印业主名称,声明变量类型
-- 语法
变量名  表名.列名%type;
-- 实例
v_name towners.name%type;
-- 练习2:打印业主名称,变量类型
declare
   -- 声明变量,用于存放name的值
   v_name t_owners.name%type;
begin
   -- 执行查询语句,获得name的值,并赋值变量
   select name into v_name from t_owners where id = 11;
   -- 打印变量
   dbms_output.put_line(v_name);
end;

3.3、变量类型练习

  • 练习3:需求:计算台账中编号为1的用户当月用水金额。
  • 要求输出:单价、吨数、金额、上月用水量,本月用水量
-- 练习3:需求:计算台账表中编号为1的用户当月用水金额。
---- 要求输出:单价、吨数、金额、上月用水量、本月用水量
declare
 v_price number;
 --上月累计用水量  t_account.num0%type
 v_num0 number;
 --本月累计用水量  t_account.num1%type
 v_num1 number;
 --使用量  		t_account.usenum%type
 v_usenum number;
 --金额
 v_money number;
 -- 吨数
 v_usenum2 number;
begin 
  -- 单价
  v_price := 3.45;
  -- 查询数据,获得用水量、金额
  select num0,num1,usenum,money into v_num0,v_num1,v_usenum,v_money from t_account where id = 1;
  -- 吨数 19920 --> /1000 --> 19.920  --> 19.92
  v_usenum2 := round(v_usenum / 1000 , 2 );
  -- 打印
  dbms_output.put_line('单价' || v_price || '、吨数'|| v_usenum2 ||'、金额'|| v_money ||'、上月用水量'|| v_num0 ||'、本月用水量'|| v_num1);
  
end;

3.4、变量类型 %rowtype

  • 通过 %rowtype 获得某一行的所有类型,相当于一个对象,存放一条记录
  • 声明变量
--语法
变量 表名%rowtype;
--实例
v_account t_account%rowtype;
  • 赋值
-- 单列
select 列名,列名2,... into 变量.列名,变量.列名2,...  from 表名;
-- 所有
select * into 变量  from 表名;
  • 实例:重写练习3:使用 %rowtype
-- 重写练习3:使用%rowtype
declare
   -- 单价
   v_price number;
   -- 声明行变量
   v_account t_account%rowtype;
begin 
   -- 单价
   v_price := 3.45;
   -- 保存一行数
   select * into v_account from t_account where id = 1;
   -- 打印
   dbms_output.put_line('单价' || v_price ||'、金额'|| v_account.money ||'、上月用水量'|| v_account.num0 ||'、本月用水量'|| v_account.num1);
end;

4、异常

-- 语法
declare
begin
	-- 正常代码
	-- 异常块
	exception
		when 异常类型 then
			处理
		when 异常类型 then
			处理
		....
end;
-- 常见异常类型:
no_date_found , 没有数据异常,查询结果为null
too_many_rows,太多行,查询结果大于1条
  • 练习4:查询台账表,id为1所有信息,并打印部分 -- 正常情况
-- 异常处理
-- 练习4:查询台账表,id为1所有信息,并打印部分
declare 
  v_account t_account%rowtype;
begin 
  --查询
  select * into v_account from t_account where id = 1;
  --打印
  dbms_output.put_line('上月用水量' || v_account.num0 || '本月用水量' || v_account.num1);
  -- 异常处理
  exception 
    when no_data_found then
      dbms_output.put_line('没有查询到数据');
    when too_many_rows then
      dbms_output.put_line('查询结果大于1条');
end;
  • 练习4:查询台账表,id为1所有信息,并打印部分 -- 异常情况--没有数据
-- 异常处理
-- 练习4:查询台账表,id为1所有信息,并打印部分
declare 
  v_account t_account%rowtype;
begin 
  --查询
  select * into v_account from t_account where id = 999;
  --打印
  dbms_output.put_line('上月用水量' || v_account.num0 || '本月用水量' || v_account.num1);
  -- 异常处理
  exception 
    when no_data_found then
      dbms_output.put_line('没有查询到数据');
    when too_many_rows then
      dbms_output.put_line('查询结果大于1条');
end;
  • 练习4:查询台账表,id为1所有信息,并打印部分 -- 异常情况--查询多条数据
-- 练习4:查询台账表,id为1所有信息,并打印部分
declare 
  v_account t_account%rowtype;
begin 
  --查询
  select * into v_account from t_account;
  --打印
  dbms_output.put_line('上月用水量' || v_account.num0 || '本月用水量' || v_account.num1);
  -- 异常处理
  exception 
    when no_data_found then
      dbms_output.put_line('没有查询到数据');
    when too_many_rows then
      dbms_output.put_line('查询结果大于1条');
end;

5、判断语句 if

  • if 语法
if 条件 then

elsif 条件2 then

els if 条件3 then

...

else 

end if;
  • 实例:设置三个等级的水费 5吨以下2.45元/吨 5吨到10吨部分3.45元/吨 超过10吨部分4.45 ,根据使用水费的量来计算阶梯水费
-- 需求:设置三个等级的水费 5吨以下2.45元/吨  5吨到10吨部分3.45元/吨  ,超过10吨部分4.45 ,根据使用水费的量来计算阶梯水费。
declare
  -- 定义3个水费价格
  v_price1 number;
  v_price2 number;
  v_price3 number;
  -- 台账记录
  v_account t_account%rowtype;
  -- 使用量(吨数)
  v_usenum2 number;
  -- 金额
  v_money number;
begin
  -- 确定水费价格
  v_price1 := 2.45;
  v_price2 := 3.45;
  v_price3 := 4.45;
  -- 查询记录
  select * into v_account from t_account where id = 4;
  -- 计算使用量
  v_usenum2 := round(v_account.usenum / 1000 , 2);

  -- 根据使用量,计算阶梯水费

  if v_usenum2 <= 5 then 
    --- 小于5吨 : 使用量 * 2.45 
    v_money := v_usenum2 * 2.45;
  elsif v_usenum2 <= 10 then
    --- 小于10吨: 5 * 2.45 + (使用量 - 5) * 3.45
    v_money := 5 * 2.45 + (v_usenum2 - 5) * 3.45;
  else 
    --- 大于10吨: 5 * 2.45 + 5 * 3.45 + (使用量 - 10) * 4.45
    v_money := 5 * 2.45 + 5 * 3.45 + (v_usenum2 - 10) * 4.45;
  end if;

  -- 打印水费
  dbms_output.put_line(v_money);
end;

6、循环

6.1、无条件循环

--语法
loop
	-- 代码
	-- 结束循环
	exit;
end loop;
  • 课上:输出从1开始的100个数
--练习:输出从1开始的100个数
declare
  v_i int := 1 ;
begin
  loop
    dbms_output.put_line(v_i);
    -- 累加
    v_i := v_i + 1;
    -- 退出
    if v_i > 100 then
      exit;
    end if;
  end loop;
end;

6.2、while循环

--语法
while 条件
loop
	--内容
end loop;
  • 课上练习:求 1-100和,并打印
-- 练习:求1-100和,并打印
declare
  --计数器
  v_i int := 1;
  --求和变量
  v_sum int := 0;
begin 
  while v_i <= 100
    loop
      --求和
      v_sum := v_sum + v_i;
      
      --累加
      v_i := v_i + 1;
    end loop;
  --打印
  dbms_output.put_line(v_sum);
end;

6.3、for循环

  • 语法
for 变量 in 起始值..终止值
loop
	-- 循环体
end loop;
  • 练习1:
-- 练习1:打印1--100数
declare
 v_i int;
begin
  for v_i in 1..100
    loop
      dbms_output.put_line(v_i);
    end loop;
end;
  • 练习2:
-- 练习2:求1-100所有偶数的和,并打印
declare 
 -- 计数变量
 v_i int;
 -- 求和变量
 v_sum int := 0;
begin 
  for v_i in 1..100
    loop
      -- mod() 用于求余
      if mod(v_i,2) = 0 then
        v_sum := v_sum + v_i;
      end if;
    end loop;
  dbms_output.put_line(v_sum);
end;
  • 练习3:99乘法表
-- 练习3:99乘法表
--- 输出内容,是否换行
declare
begin 
  -- 一行输出
  dbms_output.put('abc');
  -- 换行输出
  dbms_output.put_line('123');
end;

-------- 普通循环
declare
 v_i int;
begin 
  -- 循环
  for v_i in 1..9
    loop
      dbms_output.put_line(v_i);
    end loop;
end;
-------- 嵌套循环
declare
 v_i int;
 v_j int;
begin 
  -- 嵌套循环
  for v_i in 1..9
    loop
      -- 内部循环
      for v_j in 1..9
        loop
          dbms_output.put_line(v_i || v_j);
        end loop;
    end loop;
end;

-------99乘法表
declare
 v_i int;
 v_j int;
begin 
  -- 嵌套循环
  for v_i in 1..9
    loop
      -- 内部循环
      for v_j in 1..v_i
        loop
          dbms_output.put(v_j || ' * ' || v_i || ' = ' || (v_i * v_j) );
          dbms_output.put('   ');
        end loop;
      dbms_output.put_line('');
    end loop;
end;