13-Oracle学习_PL/SQL

PL/SQL

一, 概述

 1, 每种数据库都有内部的语言
 2, PL/SQL是 Oracle 中使用的编程语言    
 3, 编程语言
    ① 数据类型
    ② 语法
 4, Procedural Language/SQL 
    过程化语言, 也就是带有分支循环的语言
    SQL语言功能太单一, 需要结合其他的语言完成复杂的功能.
    PL/SQL是Oracle数据库对SQL语句的扩展。
    在普通SQL语句的使用上增加了编程语言的特点,
    所以PL/SQL就是把数据操作和查询语句组织在PL/SQL代码的过程性单元中,
    通过逻辑判断、循环等操作实现复杂的功能或者计算的程序语言。


二, PL/SQL

1, 匿名块

  (1)格式
     [declare
        变量声明
     ]
     begin
        正常流程语句
     [exception
        异常处理
     ]
     end    
  (2)HelloWorld
SQL> set serveroutput on;
SQL> begin
  2          dbms_output.put_line('Hello World!');
  3      end;
  4      /
Hello World!
     注: 必须打开输出开关, 才能看到输出显示
  (3)declare 
    ① 变量名命名惯例, 以 "v_" 为前缀
    ② declare 变量名 类型;
    ③ 赋值语句->  变量名 := 值;
SQL> declare
  2    v_name varchar2(20);
  3  begin
  4    v_name := 'myname';
  5    dbms_output.put_line(v_name);
  6  end;
  7  /
myname
  (4)exception
SQL> declare
  2    v_num number := 0;
  3  begin
  4    v_num := 1 / v_num;
  5    dbms_output.put_line(v_num);
  6  exception
  7    when others then
  8      dbms_output.put_line('error');
  9  end;
 10  /
error    

2, 变量声明的规则

(1) 变量名不能使用保留字, 如 from, select 等
(2) 第一个字符必须是字母
(3) 变量名最多包含30个字符
(4) 不要与数据库的表或者列同名
(5) 每一行只能声明一个变量

3, 常用变量类型

(1) binary_integer  : 整数, 主要用来计数而不是用来表示字段类型.
(2) number          : 数字类型
(3) char            : 定长字符串
(4) varchar(2)      : 变长字符串
(5) date            : 日期
(6) long            : 长字符串, 最大 2GB
(7) boolean         : 布尔类型, 取值 true/false/null

4, 简单变量

(1)
declare
    v_temp number(1) := 0;
    v_count binary_integer := 0;
    v_sal number(7, 2) := 4000.00;
    v_date date := sysdate;
    v_pi constant number(3, 2) := 3.14;     -- 常量
    v_valid boolean := false;
    v_name varchar2(20) not null := 'MyName';   -- 不能取空值
begin
    dbms_output.put_line('v_temp value:' || v_temp);
end;


(2) 变量的作用
    通常用于存储某张表的字段的值.
(3) %type , 同步 表字段/其他变量 的类型
declare
    v_empno number(4);       -- 自定义类型   
    v_empno2 emp.empno%type; -- emp表的empno字段的类型
    v_empno3 v_empno2%type;  -- v_empno2的类型
begin
    dbms_output.put_line('test %type');
end;



5, 复杂变量 table record

(1) Table 变量类型 , 类似 java中的数组
注: 先声明类型, 在声明该类型的变量
declare
    type type_table_empno           -- 声明 类型 
        is table of emp.empno%type  -- 指定是 table类型 以及每个元素的类型
        index by binary_integer;    -- 指定下标的类型


    -- 声明一个 type_table_empno 类型的变量
    v_empnos type_table_empno;
begin
    v_empnos(0) := 1111;
    v_empnos(1) := 2222;
    v_empnos(2) := 3333;
    dbms_output.put_line(v_empnos(1));
end;


    
(2) Record 变量类型, 类似于 C语言中的结构体

declare
    type type_record_dept is record
        (
            deptno dept.deptno%type,
            dname dept.dname%type,
            loc dept.loc%type
        );
    v_temp type_record_dept;
begin
    v_temp.deptno := 50;
    v_temp.dname := 'zhangsan';
    dbms_output.put_line('v_temp.deptno ' || v_temp.deptno);
    dbms_output.put_line('v_temp.dname ' || v_temp.dname);
end;


② 使用 %rowtype声明 record变量
declare
    v_temp dept%rowtype;
begin
    v_temp.deptno := 55;
    v_temp.dname := 'zhangsan';
    v_temp.loc := 'WuHan';
    dbms_output.put_line('v_temp.deptno ' || v_temp.deptno);
    dbms_output.put_line('v_temp.dname ' || v_temp.dname);
    dbms_output.put_line('v_temp.loc ' || v_temp.loc);
end;




6, SQL语句的运用 into

(1) select into
注: 有且只能返回一行数据
① %type
declare
    v_ename emp.ename%type;
    v_sal emp.sal%type;
begin
    select ename, sal into v_ename, v_sal
    from emp
    where empno = 7566;
    dbms_output.put_line('v_ename ' || v_ename);
    dbms_output.put_line('v_sal ' || v_sal);
end;


②  %rowtype
declare
    v_emp emp%rowtype;
begin
    select * into v_emp 
    from emp 
    where empno = 7566;
    dbms_output.put_line('v_emp.empno ' || v_emp.empno);
    dbms_output.put_line('v_emp.ename ' || v_emp.ename);
    dbms_output.put_line('v_emp.sal ' || v_emp.sal);   
end;


(2) insert into
create table dept2 as select * from dept;
declare
    v_deptno dept.deptno%type := 50;
    v_dname dept.dname%type := 'game';
    v_loc dept.loc%type := 'WuHan';
begin
    insert into dept2 values(v_deptno, v_dname, v_loc);
    commit;
end;


(3) update -- sql%rowcount
注: 关键字sql, 其属性rowcount, 刚刚执行的语句影响了几条记录
create table emp2 as select * from emp;
declare
    v_deptno emp2.deptno%type := 10;
    v_count number;
begin
    update emp2 set sal = sal / 2 where deptno = v_deptno;
    -- select count(*) into v_count from emp; --影响一条记录
    dbms_output.put_line(sql%rowcount || ' 条记录被影响');
    commit;
end;




7, 循环 loop

(1) 类似于 java中 do{ .. }while(); 循环
declare
    i binary_integer := 1;
begin
    loop
        dbms_output.put_line(i);
        i := i + 1;
        exit when ( i >= 11 );
    end loop;
end;


(2) 类似于 java中 while(){} 循环
declare
    i binary_integer := 1;
begin   
    while i < 11 loop
        dbms_output.put_line(i);
        i := i + 1;
    end loop;
end;


(3) 类似于 java中 for(){} 循环
① for each
begin
    for i in 1..10 loop
        dbms_output.put_line(i);
    end loop;
end;


② 反转
begin
    for i in reverse 1..10 loop
        dbms_output.put_line(i);
    end loop;
end;




8, IF语句

① 
格式:
    if condition then
        ...
    end if;
例子:
declare
    x number := 1;
begin
    if x < 10 then
        dbms_output.put_line(x || ' is less than 10');
    end if;
end;



格式:
    if condition then
        ...
    else
        ...
    end if;
例子:
declare
    x number(2) := 11;
begin
    if x < 10 then
        dbms_output.put_line(x || ' is less than 10');
    else
        dbms_output.put_line(x || ' is bigger than 10');
    end if;
end;



格式:
if condition_1 then
    ...
elsif condition_2 then
    ...
else
    ...
end if;
举例:
declare
    x number(2) := 10;
begin
    if x < 10 then
        dbms_output.put_line(x || ' is less than 10');
    elsif x < 20 then
        dbms_output.put_line(x || ' is less then 20');
    else
        dbms_output.put_line(x || ' is bigger than 20');
    end if;
end;




9, 异常处理

(1) too_many_rows
declare
    v_temp number(4);
begin
    select empno into v_temp from emp where deptno = 10;
exception
    when too_many_rows then
        dbms_output.put_line('太多记录了');
    when others then
        dbms_output.put_line('error');
end;


(2) no_data_found
declare
    v_temp number(4);
begin
    select empno into v_temp from emp where empno = 2222;
exception 
    when no_data_found then
        dbms_output.put_line('没有数据');
end;


(3) 记录错误
-- 记录错误的日志表
create table errorlog
(
    id number primary key,
    errorcode number,
    errormsg varchar2(1024),
    errordate date
);


-- 创建序列
create sequence seq_errorlog_id start with 1 increment by 1;


-- 出错后, 插入错误日志表, SQLCODE, SQLERRM
declare
    v_deptno dept.deptno%type := 10;
    v_errorcode errorlog.errorcode%type;
    v_errormsg errorlog.errormsg%type;
begin
    delete from dept where deptno = v_deptno;
    commit;
exception
    when others then
        rollback;
        v_errorcode := SQLCODE;
        v_errormsg := SQLERRM;
        insert into errorlog 
          values(seq_errorlog_id.nextval, v_errorcode, v_errormsg, sysdate);
        commit;
end;


-- clean
-- drop sequence seq_errorlog_id;
-- drop table errorlog;




10, case 语句

参考: http://www.cnblogs.com/eshizhan/archive/2012/04/06/2435493.html
(1) CASE WHEN 表达式有两种形式
① 简单 case函数
case sex
  when '1' then '男'
  when '2' then '女'
  else '其他' 
end  


② case 搜索函数
case
  when sex = '1' then '男'
  when sex = '2' then '女'
  else '其他'
end


(2) CASE WHEN 在语句中不同位置的用法
① SELECT CASE WHEN 用法
SELECT grade, COUNT (CASE WHEN sex = 1 THEN 1      /*sex 1为男生,2位女生*/
                     ELSE NULL
                     END) 男生数,
              COUNT (CASE WHEN sex = 2 THEN 1
                     ELSE NULL
                     END) 女生数
FROM students GROUP BY grade;


② WHERE CASE WHEN 用法
SELECT T2.*, T1.*
FROM T1, T2
WHERE (CASE WHEN T2.COMPARE_TYPE = 'A' AND T1.SOME_TYPE LIKE 'NOTHING%' THEN 1
       WHEN T2.COMPARE_TYPE != 'A' AND T1.SOME_TYPE NOT LIKE 'NOTHING%' THEN 1
       ELSE 0
       END) = 1


③ GROUP BY CASE WHEN 用法

SELECT  
        CASE WHEN salary <= 500 THEN '1'  
        WHEN salary > 500 AND salary <= 600  THEN '2'  
        WHEN salary > 600 AND salary <= 800  THEN '3'  
        WHEN salary > 800 AND salary <= 1000 THEN '4'  
        ELSE NULL 
        END salary_class, -- 别名命名
        COUNT(*)  
FROM Table_A  
GROUP BY  
        CASE WHEN salary <= 500 THEN '1'  
        WHEN salary > 500 AND salary <= 600  THEN '2'  
        WHEN salary > 600 AND salary <= 800  THEN '3'  
        WHEN salary > 800 AND salary <= 1000 THEN '4'  
        ELSE NULL 
        END;




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值