pl/sql 的概念

1、结构化查询语言(Structured Query Language,简称SQL)是用来访问关系型数据库一种通用语言,其执行特点是非过程化,不需要用户指定对数据的存放方法,也不需要用户了解具体的数据存放方式,即不用指明执行的具体方法和途径,而是简单的调用相应语句来直接取得结果即可。

2、pl/sql不仅仅是一个数据库查询语言,而且也是一个编程语言。PL/SQL 是过程化语言,对SQL的补充,可以用来实现比较复杂的业务逻辑。

3、T-SQL是Transact-SQL,是微软对SQL的扩展,具有SQL的主要特点,同时增加了变量、运算符、函数、流程控制和注释等语言元素,使得其功能更加强大。

Transact-SQL 是具有批量与区块特性的SQL指令合集,数据库开发人员可以利用他来撰写数据部分的商业逻辑(Data-based Business Logic),以强制限制前端应用程序对数据的控制能力。

同时,他也是数据库对象的主要开发语言。

 

一、语法结构

declare  声明变量----必须一行一个变量用分号结束每一行声明 ;

begin

     SQL语句

     PL/SQL控制语句

exception

错误发生时执行的动作

end;

 

例题:打印系统当前日期

declare

current_date date:=sysdate;--一行只能有一个变量必须以分号结尾

begin

 dbms_output.put_line(current_date);

end;

 

二、变量的使用

1、type --不知道数据类型(V_表示变量的意思)

declare

v_empename emp.ename%type;

begin

  select ename into v_empename from emp where empno=7788;

  dbms_output.put_line(v_empename);

end;

  

例题:查询

declare

  v_empno emp.empno%type;

begin

    select empno into v_empno from emp where ename='SCOTT';

    dbms_output.put_line(v_empno||' '||'SCOTT');

end;

  

 

2、rowtype --整张表都不知道数据类型

 

例题:打印员工编号为7788的姓名,雇佣日期

declare

v_a emp%rowtype;

begin

   select * into v_a from emp where empno=7788;

   dbms_output.put_line(v_a.empno||' '||v_a.ename||' '||v_a.hiredate);

end;

 

例题:使用PL/SQL显示员工编号为7788的员工编号,姓名,雇用日期,部门名称。

显示格式例如:员工编号:7788,姓名:SCOTT,雇用日期:1978-03-21,部门:RESEARCH。

 

declare

 v_e emp%rowtype;

 v_d dept%rowtype;

begin

   select * into v_e from emp where empno=7788;

   select * into v_d from dept where deptno=( select deptno from emp where empno=7788);

   dbms_output.put_line('员工编号:'||v_e.empno||', 姓名:'||v_e.ename||', 雇佣日期:'||to_char(v_e.hiredate,'yyyy-ww-dd')||', 部门:'||v_d.dname||'。');

end;

 

例题:输出姓名为SMITH 的员工编号,工作,工资。

declare

  v_a emp%rowtype;

begin

    select * into v_a from emp where ename='SMITH';

    dbms_output.put_line(v_a.empno||' '||v_a.job||' '||v_a.sal);

end;

  

3、变量的初始化

(1)constant 用在数据类型前不能进行第二次赋值

(2)not null 用在数据类型后必须要给赋值

  

declare 

  v_a  constant number(10) :=10;

  v_b number not null :=0;

begin

(错误,不能赋值)

    dbms_output.put_line(v_a);

    dbms_output.put_line(v_b);

end;

 

4、变量的赋值

变量赋值有两种方法:(1)使用“:=”

(2)select ... into  :查询结果赋值给变量、

有多个字段的查询结果赋值给多个变量

整行数据赋值

 

 

三、分支循环控制语句

 

1、三种条件分支结构

 

(1)if  then   

declare

v_a number(5):=9;

begin 

      if v_a<10 then 

      dbms_output.put_line('我爱睡觉'); 

      end if;

end;

     

(2)if  then ; else

declare

v_a number(5) := 9;

begin

  if v_a > 10 then

  dbms_output.put_line('我爱睡觉');

  else

  dbms_output.put_line('我爱吃芒果');

  end if;

end;

 

(3)if  then ; elsif then;  else

declare

v_a number(5) := 6;

begin

    if v_a > 10 then

    dbms_output.put_line('我爱睡觉');

    elsif v_a<10 then

    dbms_output.put_line('我爱吃火锅');

    elsif ... then ...

...

else

    dbms_output.put_line('我爱吃芒果');

    end if;

end;

 

例题:给员工加薪水,加薪规则如下:

 

create table myemp as select * from emp   

 

declare

v_sal myemp.sal%type;

begin

  select avg(sal) into v_sal from myemp;

  if v_sal<=1000 then

    update myemp set sal=sal*1.2;

  elsif v_sal>1000 and v_sal<=2000 then

    update myemp set sal=sal*1.15;

  elsif v_sal>2000 and v_sal<=3000 then

    update myemp set sal=sal*1.1;

  else

    update myemp set sal=sal*1.05;

  end if;

end;

 

select * from myemp

 

2、三种循环结构

 

(1)基本循环

declare

v_a number(2):=0;

begin

  loop

    v_a:=v_a+1;

    exit when v_a>3;

    end loop;

    dbms_output.put_line(v_a);

end;

  

2、while_loop 循环

declare

v_a number(2):=0;

begin 

  while v_a<=3

    loop

      v_a:=v_a+1;

      end loop;

    dbms_output.put_line(v_a);  

end;

  

 

3、for_loop 循环

 

例题:输出1..10 相加结果

declare

v_a number(2):=1;

v_sum number(2):=0;

begin

  for v_a in 1..10

   loop

     v_sum:=v_sum+v_a;

     end loop;

     dbms_output.put_line(v_sum);   

end;

 

例题:向部门表dept1中插入10条数据,部门编号从41到50。部门名称分别是dept41,dept42,…,dept50。

create table dept1 as select * from dept

 

declare

dept1 dept%rowtype;

begin

  for v_a in 41..50

    loop

    insert into dept1 (deptno,dname)

    values(v_a,'dept'||v_a);

    end loop;

end;

  

select * from dept1

 

declare

dept1 dept%rowtype; 

v_a number:=51;

begin 

  loop

    v_a:=v_a+1;

    exit when v_a>60;

    insert into dept1(deptno,dname)

    values(v_a,'dept'||v_a);

    end loop;

  end;

 

declare

dept1 dept%rowtype;

v_a number:=61; 

begin

  while v_a<70 loop

    v_a:=v_a+1;

    insert into dept1(deptno,dname)

    values(v_a,'dept'||v_a);

    end loop;

  end; 

 

四、游标

其定义为:用游标来指代一个DML SQL操作返回的结果集。即当一个对数据库的查询操作返回一组结果集时,用游标来标注这组结果集,以后通过对游标的操作来获取结果集中的数据信息。

 

优点:(了解)

1 对从表中检索出的数据进行操作非常灵活。

2 允许应用程序对查询语句select 返回的行结果集中每一行进行相同或不同的操作。

3 提供对基于游标位置而对表中数据进行删除或更新的能力。

缺点:

1 游标速度较慢。

2 处理大数据量时,效率低下,占用内存大

 

 

例题:查询emp表中empno和相对应的ename


1、显性游标---有明确的游标声明和操作过程。操作过程包括打开游标,取值,关闭游标。(loop循环)


Declare--loop循环

v_empno number(5);

v_ename varchar2(20);

cursor c_a is select empno,ename from emp;

begin

  open c_a;

  loop

    fetch c_a into v_empno,v_ename;

    exit when c_a%notfound;

    dbms_output.put_line(v_empno||v_ename);

    end loop;

    close c_a;

end;

 

Declare----while循环

      v_empno   number(4);

      v_ename   varchar2(20);

      Cursor c_emp is select  empno, ename  from emp;

Begin

      open c_emp;

      fetch c_emp into  v_empno,  v_ename;

      while c_emp%found  loop

          dbms_output.put_line(v_empno ||' '||v_ename );

          fetch c_emp into  v_empno,  v_ename;

      end loop;

      close c_emp;

End; 

 

特例,for 循环,不用打开和关闭游标

 

 

2、隐性游标----没有明确的游标声明和操作过程。

对于非查询语句,如修改、删除操作,则由ORACLE 系统自动地为这些操作设置游标并创建其工作区,这些由系统隐含创建的游标称为隐性游标。在隐性游标的工作区中,所存放的数据是与用户自定义的显示游标无关的、最新处理的一条SQL 语句所包含的数据。

insert、update、delete、以及由 select into 所影响的行,都有隐性游标。

 

declare

v_a emp%rowtype;

cursor c_a is select empno,ename from emp;

begin

  for v_a in c_a

    loop

    dbms_output.put_line(v_a.empno||v_a.ename);

    end loop; 

  end;

 

3、游标的属性

显性游标

(1)%notfound 属性。当最近一次读记录(fetch),成功取到值,此数据为

(2)%found 属性,与 %notfound 相反

(3)%rowcount 属性, 返回由 insert、update 或 delete 所影响的行数

对于游标,则 %rowcount 表示FETCH成功的数据条数。如果 open 游标,但没有进行 fetch,则 rowcount 值为0

(4)%isopen 属性,当游标已打开时返回

 

隐性游标

(1)%notfound 属性

(2)%found 属性

(3)% rowcount 属性

(4)%isopen 属性(总是 false)



五、异常 exception

异常情况处理(exception)是用来处理正常执行过程中出现未预料的错误事件,使得程序遇到错误能继续运行。

常见异常名称:

 

 

相除

方法一:

declare

v_a number:='&请输入v_a'; 

v_b number:='&请输入v_b'; 

v_c number;

begin

  v_c:=v_a/v_b;

  dbms_output.put_line(v_c);

  exception

    when ZERO_DIVIDE then

      dbms_output.put_line('fff');

  end;

 

方法二:

declare

v_a number:='&请输入v_a'; 

v_b number:='&请输入v_b'; 

v_c number;

begin

  v_c:=v_a/v_b;

  dbms_output.put_line(v_c);

  exception

    when others then

      dbms_output.put_line('fff');

  end;

 

相加

declare

v_a number:='&请输入v_a';

v_b number:='&请输入v_b';

v_c number;

begin

  v_c:=v_a+v_b;

  dbms_output.put_line(v_c);

  exception

    when others then

    dbms_output.put_line(777);

    end;