Oracle:PL/SQL基础笔记分享

一、基本结构

[declare declaration_statements;]

begin

executable_statements;

[exception exception_handling_statements;]

end;

/

declare变量,begin…end主体(可嵌套其他块),exception处理可能出现的任何执行错误,PL/SQL语句需要使用’/‘结尾才能被执行


二、常量和变量

①数据类型

类型

说明

boolean

布尔型,true\false\null

binary_integer

带符号整数,-231~231

natural

binary_integer的子类型,非负整数

naturaln

binary_integer的子类型,不为null的非负整数

positive

binary_integer的子类型,正整数

positiven

binary_integer的子类型,不为null的正整数

signtype

binary_integer的子类型,-1\0\1

pls_integer

带符号整数,-231~231,与binary_integer相似。若溢出会发生异常

simple_integer

取值与binary_integer相同,不能存储null值,若溢出不会发生异常,只会简单截断结果

string

与varchar2相同

record

一组其他类型的组合

ref cursor

指向一个行集的指针

②常量

声明时必须赋值

constant_name constant data_type {:=|default} value;

:=为赋值符号,也可以使用default代替(初始化常量或变量时)

③变量

variable_name data_type [[not null] {:=|default} value];

④在PL/SQL中使用变量和常量

set serveroutput on       
 /*在SQL*Plus中显示DBMS_OUTPUT.put_line输出内容的必做事项,即打开服务器输出*/
declare
  emp_number constant number(4) := 7900;
  emp_name varchar2(10);
  emp_job varchar2(9);
  emp_sal number(7,2);
begin
select ename,job,sal 
into emp_name,emp_job,emp_sal
from emp where empno=emp_number;        /*Oracle中用||连接两个字符串*/
dbms_output.put_line('查询的员工的编号为:'||emp_number);
dbms_output.put_line('该员工的姓名为:'||emp_name);
dbms_output.put_line('该员工的职位为:'||emp_job);
dbms_output.put_line('该员工的工资为:'||emp_sal);
end;
/

输出:

查询的员工的编号为:7900

该员工的姓名为:JAMES

该员工的职位为:CLERK

该员工的工资为:950


三、%TYPE类型和%ROWTYPE类型

①%TYPE类型

可解决无法确定变量数据类型的问题:用于隐式地将变量的数据类型指定为对应列的数据类型

variable_name table_name.column_name%type

[[not null] {:=|default}value];

set serveroutput on
declare
  emp_number constant number:=7900;
  emp_name emp.ename%type;
  emp_job emp.job%type;
  emp_sal emp.sal%type;
begin
select ename,job,sal 
into emp_name,emp_job,emp_sal
from emp where empno=emp_number;
end;
/
dbms_output.put_line('工号:'||emp_number);
dbms_output.put_line('姓名:'||emp_name);
dbms_output.put_line('职位:'||emp_job);
dbms_output.put_line('工资:'||emp_sal);

②%ROWTYPE类型

相对于%TYPE列数据,%ROWTYPE针对于行数据,可以存储表中一行数据。

variable_name table_name%rowtype;

set serveroutput on
declare
  emp_number constant emp.empno%type:=7900;
  one_emp emp%rowtype;
begin
  select *
  into one_emp
  from emp where empno=emp_number;
  dbms_output.put_line('工号:'||emp_number);
  dbms_output.put_line('姓名:'||one_emp.ename);
  dbms_output.put_line('职位:'||one_emp.job);
  dbms_output.put_line('工资:'||one_emp.sal);
end;
/

四、记录类型和表类型

①记录类型

可存储由一个或多个字段组成的一行数据

type record_name is record (

field_name data_type [[not null] {:=|default}value]

[,…]

);

set serveroutput on
declare
  type emp_type is record (
      empno number(4),
      ename varchar2(10),
      job varchar2(9),
      sal number(7,2)
  );
  one_tmp emp_type;
  begin
    select empno,ename,job,sal
    into one_emp
    from emp where empno=7900;
    dbms_output.put_line('工号:'||one_emp.empno);
    dbms_output.put_line('姓名:'||one_emp.ename);
    dbms_output.put_line('职位:'||one_emp.job);
    dbms_output.put_line('工资:'||one_emp.sal);
end;
/

②表类型

相对于记录类型可以处理多行数据,类似表

type table_name is table of data_type [not null]

index by binary_integer;

index by binary_integer:指定系统创建一个主键索引,用于引用表类型变量中的特定行

set serveroutput on
declare
  type my_emp is table of emp%rowtype
  index by binary_integer;
  new_emp my_emp;
begin
  new_emp (1).empno := 6800;
  new_emp (1).ename := 'TRACY';
  new_emp (1).job := 'CLERK';
  new_emp (1).sal := 2500;
  new_emp (2).empno := 6900;
  new_emp (2).ename := 'LUCY';
  new_emp (2).job := 'MANAGER';
  new_emp (2).sal := 4000;
  dbms_output.put_line(new_emp (1).empno||','||
                      new_emp (1).ename||','||
                      new_emp (1).job||','||
                      new_emp (1).sal);
  dbms_output.put_line(new_emp (2).empno||','||
                      new_emp (2).ename||','||
                      new_emp (2).job||','||
                      new_emp (2).sal);
  end;
  /

输出:

6800,TRACY,CLERK,2500

6900,LUCY,MANAGER,4000

删除(表类型变量中的)记录

variable_name delete [(index_number)];

其他操作(表类型变量)

count:返回表类型变量中的记录数

first:返回表类型变量的第一行索引

last:返回表类型变量的最后一行索引

next:返回表类型变量的下一行索引


五、程序注释

--:单行注释

/*…*/:多行注释


六、条件选择语句

①if条件语句

if <expression1> then PL/SQL_statement1;

end if; --最简单形式

set serveroutput on
declare
  num number := 8;
begin
  if mod(num,2)=0 then
    dbms_output.put_line(num||'为偶数');
  end if;
end;
/

if <expression1> then PL/SQL_statement1;

else PL/SQL_statement2;

end if; --与else结合

if <expression1> then PL/SQL_statement1;

elsif <expression2> then PL/SQL_statement2;

else PL/SQL_statement3;

end if; --与elsif结合

②case表达式

case search_expression

when expression1 then result1;

when expression2 then result2;

when expressionN then resultN;

[else default_result;]

end case; --第一种便于比较确定的一个值

set serveroutput on
declare
  day number := 3;
begin
  case day
  when 1 then dbms_output.put_line('Monday');
  when 2 then dbms_output.put_line('Tuesday');
  when 3 then dbms_output.put_line('Wednesday');
  ……
  when 7 then dbms_output.put_line('Sunday');
  else dbms_output.put_line('Error');
  end case;
end;
/

输出:Wednesday

case

when condition1 then result1;

when condition2 then result2;

when conditionN then resultN;

[else default_result];

end case; --第二种便于比较确定的一个范围

set serveroutput on
declare
  score binary_integer := 61;
begin
  case 
  when score >= 90 then dbms_output.put_line('优秀');
  when score >= 80 then dbms_output.put_line('良好');
  when score >= 60 then dbms_output.put_line('及格');
  else dbms_output.put_line('不及格');
  end case;
end;
/

输出:及格


七、循环语句

①loop循环语句

loop

statements;

exit [when condition]; --退出循环

end loop;

set serveroutput on
declare
  i binary_integer := 2;
  n binary_integer := 1;
begin
  loop
    n := n*i;
    i := i+1;
    exit when i>10;
  end loop;
  dbms_output.put_line('n!='||n);
end;
/

输出:n!=3628800

②while循环语句

while condition

loop

statements;

end loop;

set serveroutput on
declare 
  i binary_integer := 2;
  n binary_integer := 1;
begin
  while i<=10
  loop 
    n:=n*i;
    i:=i+1;
  end loop;
  dbms_output.put_line('n!='||n);
end;

输出:n!=3628800

③for循环语句

for loop_variable in [reverse] lower_bound..upper_bound

loop

statements;

end loop;

set serveroutput on
begin
  for i in 1..20 loop
    if mod(i,3)=0 then
      dbms_output.put_line(i);
    end if;
  end loop;
end;

八、游标

①显示游标

声明游标:cursor cursor_name[(parameter[,parameter]…)]

[return return_type] is select_statement;

parameter_name [in] datatype [{:=|default} expression]

cursor emp_info (dept_no number := 20)		--声明一个带参数的游标
  is
  select empno,ename,job,sal
  from emp where deptno=dept_no;

打开和关闭游标:open cursor_name [(value[,value]…)];

close emp_info;

open emp_info;
open emp_info(10);			--打开游标传入参数
close emp_info;

检索数据:fetch cursor_name into {variable_list|record_variable};

fetch emp_info into emp_record;

游标中包含一个指针,每执行一个fetch时,该指针将自动移动到结果集的下一行。如果在循环中使用fetch语句,这样每一次循环都会从表中读取一行数据,从而遍历游标中的每行数据。

set serveroutput on
declare
  cursor emp_info (dept_no number := 20)
  is
  select empno,ename,job,sal
  from emp where deptno=dept_no;
  type emp_type is record(
            empno number(4),
            ename varchar2(10),
            job varchar2(9),
            sal number(7,2)
  );
  emp_record emp_type;

begin
  open emp_info(10);  
  loop
    fetch emp_info into emp_record;
    exit when emp_info%notfound;     --当游标找不到直接退出循环
      dbms_output.put('行号'||emp_info%rowcount);
      dbms_output.put(','||emp_record.empno);
      dbms_output.put(','||emp_record.ename);
      dbms_output.put_line(','||emp_record.sal);
  end loop;
  close emp_info;
end;
/

输出:

行号1,7782,CLARK,MANAGER,2450

行号2,7839,KING,PRESIDENT,5000

行号3,7934,MILLER,CLERK,1300

游标的几个属性

%found:返回布尔类型的值。用于判断最近一次读取记录时是否有数据行返回,如果有则返回true,否则返回false

%notfound:返回布尔类型的值。与%found相反

%isopen:返回布尔类型的值。用于判断游标是否打开

%rowcount:返回数字类型的值。用于返回已经从游标中读取的记录数

②隐式游标

指非PL/SQL程序中定义的而且是在PL/SQL中使用update、delete语句时,Oracle系统自动分配的标。

因为修改和删除也得逐条进行,所以它们的操作与我们定义的显示游标类似

不需要打开,也不需要关闭,即在执行update、delete语句时自动打开和关闭。当使用隐式游标的属性时,需要在属性前加上SQL。Oracle创建隐式游标时,默认的游标名为SQL

set serveroutput on
declare
  var_rows number;
begin
  update emp
  set sal=sal+10
  where deptno=10;
  var_rows := SQL%rowcount;
  dbms_output.put_line('修改'||var_rows||'条记录');
end;
/

③游标for循环

不需要手动打开和关闭游标,也不需要手动判断游标是否还有返回记录,for语句中设置的循环变量本身久存储了当前检索记录的所有列值,不再需要定义变量接收记录值

for循环使用时,不能对游标进行open、fetch、close。如果游标有输入参数,则只能使用该参数的默认值

set serveroutput on
declare
  cursor emp_info(deptno:=20)
  is
  select empno,ename,job,sal
  from emp where deptno=dept_no;
  type emp_type is record
            (empno number(4),
            ename varchar2(10),
            job varchar2(9),
            sal number(7,2));
begin
  for current_row in emp_info
  loop
  dbms_output.put_line('行号'||emp_info%rowcount||current_row.ename);
  end loop;
end;
/

输出:

行号1XXX

行号2XXX

行号3XXX

行号4XXX


九、异常

①异常处理

产生异常时,若程序没有处理异常,则会被终止运行。

exception

when exception1 then

statements1;

when exception2 then

statements2;

[…]

when others then

statementsN; --放在异常语句最后(others)

②预定义异常

指Oracle系统为一些常见错误定义好的异常,如表中的主键值重复、除数为0等。如下表

sqlcode函数可以获取异常错误号,sqlerrm函数可以获取异常的具体描述信息

set serveroutput on
declare 
  var_num1 number;
  var_num2 number;
begin
  var_num1:=9;
  var_num2:=0;
  dbms_output.put_line('var_num1='||var_num1);
  dbms_output.put_line('var_num2='||var_num2);
  dbms_output.put_line(var_num1=||'/'||var_num2||'='||var_num1/var_num2);
end;
/

输出:

declare

*

第一行出现错误:

ORA-01476:除数为0

ORA-06512:在line9

zero_divide:“除数为0”异常。此时程序被终止,因为抛出异常后,程序中没有处理该异常的代码

添加对该异常处理后的代码如下

set serveroutput on
declare 
  var_num1 number;
  var_num2 number;
begin
  var_num1:=9;
  var_num2:=0;
  dbms_output.put_line('var_num1='||var_num1);
  dbms_output.put_line('var_num2='||var_num2);
  dbms_output.put_line(var_num1=||'/'||var_num2||'='||var_num1/var_num2);
exception
  when zero_divide then
    dbms_output.put_line('输入错误,除数不能为0');
end;
/

输出:

var_num1=9

var_num2=0

输入错误,除数不能为0

③非预定义异常

除了预定义异常,Oracle为其他一些异常只提供错误代码,这些同样需要处理,不过需要在PL/SQL块中使用pragma exception_int语句为其设置名称

pragma exception_init (exception_name,oracle_error_number);

set serveroutput on
declare
  foreignexception exception;
  pragma exception_init(foreignexception,-02291);
begin
  insert into emp(empno,ename,job,deptno)
  values(8900,'TOM','CLERK',70);
  exception
        when foreignexception then
        dbms_output.put_line('提供的部门编号不存在');
end;
/

输出:

提供的部门编号不存在

ORA-02291:违反完整性约束条件。该异常在Oracle预定义异常中不存在,故要用pragma为其设置名称才能处理

④自定义异常

通过使用raise触发

set serveroutput on
declare 
  no_record exception;
begin
  update emp
  set comm=comm+10
  where empno='8900';

  if sql%notfound then
    raise no_record;
  end if;

  exception
    when no_record then
    dbms_output.put_line('未更新任何记录');
end;
/

输出:

未更新任何记录

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值