PL_SQL学习

打印输出: dbms_output.put_line('AA'); 

 显示服务器输出信息  set serveroutput on; 

打印出eid=1的员工姓名:

declare
    v_name varchar2(20);
begin
    select ename into v_name 
    from emp 
    where eid = 1;
    dbms_output.put_line(v_name);
end;
/

抛出异常:

declare
    v_num number := 0;
begin
    v_num := 2/v_num;
    dbms_output.put_line(v_num);
exception
    when others then
        dbms_output.put_line('error');
end;
/

使用%type进行目标类型赋值(若表字段类型改变时变量的类型也会实时更改)

declare
    v_eid emp.eid%type;
    v_ename emp.ename%type;
    v_ename2 v_ename%type;

常用变量类型

1. binary_integer::整数,主要用来计数而不是用来表示字段类型。

2. number:数字类型,可以表示整数和小数。

3. char:定长字符串。

4. varchar2:变长字符串

5. date:日期

6. long:长字符串,最长2GB

7. boolean:布尔类型(true,false,null值)

复合数据类型:

Table变量类型(类比java中的数组)

declare 
    -- 首先声明名字为type_table_emp_eid类型的数组
    type type_table_emp_eid is table of EMP.EID%type index by binary_integer;
    v_eids type_table_emp_eid;
begin
    v_eids(0) := 12;
    v_eids(1) := 11;
    v_eids(2) := 2;
    v_eids(-1) := 6;
    dbms_output.put_line(v_eids(-1));
end;
/

Record变量类型(类比java中的类)

declare
    type type_record_emp is record
        (
            eid emp.eid%type,
            ename emp.ename%type,
            cid emp.cid%type
        );
        v_temp type_record_emp;
begin
    v_temp.eid := 4;
    v_temp.ename := 'rose';
    v_temp.cid := 4;
    dbms_output.put_line(v_temp.eid || '-' || v_temp.ename);
end;
/

使用%rowtype声明record变量(表结构发生变化时,rocord变量也会实时变化)

接下来是上面代码的优化版:

declare
    v_temp emp%rowtype;
begin
    v_temp.eid := 4;
    v_temp.ename := 'rose';
    v_temp.cid := 4;
    dbms_output.put_line(v_temp.eid || '-' || v_temp.ename);
end;
/

PL_SQL里的select查询必须和into一块用,而且保证有且只有一条记录

declare
    v_ename emp.ename%type;
    v_cid emp.cid%type;
begin
    select ename,cid into v_ename,v_cid from emp where eid = 1;
    dbms_output.put_line(v_ename || '-' ||v_cid);
end;
/

select 与 %rowtype的联合运用

declare
    v_emp emp%rowtype;
begin
    select * into v_emp from emp where eid = 1;
    dbms_output.put_line(v_emp.eid || '-'|| v_emp.ename || '-' || v_emp.cid);
end;
/

insert 的使用,别忘了commit

declare 
    v_eid emp.eid%type := 4;
    v_ename emp.ename%type := 'rose';
    v_cid emp.cid%type := 5;
begin
    insert into emp values(v_eid,v_ename,v_cid);
    commit;
end;
/

update的使用与sql%rowcount(影响记录条数统计)

declare
    v_eid emp.eid%type := 2;
    v_ename emp.ename%type := 'jeck';
begin
    update emp set ename = v_ename where eid = v_eid;
    dbms_output.put_line(sql%rowcount || '条记录被影响');
    commit;
end;
/

select语句into一条数据给变量,所以影响一行。

declare
    v_count number;
begin
    select count(0) into v_count 
    from company;
    dbms_output.put_line(sql%rowcount || '条记录被影响');
end;
/

PL_SQL中执行DDL语句时需要添加execute immediate(' xxx ')

begin
    execute immediate 
    'create table test2(
        c1 varchar(20)
    )';
end;
/

PL_SQL中的条件判断 if .. then .. elsif .. then .. else .. end if

declare
    v_cname company.cname%type;
begin
    select c.cname into v_cname 
    from company c
    where cid = 3;
    if v_cname = '腾讯' then 
        dbms_output.put_line('qq微信');
    elsif v_cname = '百度' then
        dbms_output.put_line('搜索引擎');
    else    
        dbms_output.put_line('其他公司');
    end if;
end;
/

PL_SQL中的循环

类似java中do...while循环

declare
    i binary_integer :=1;
begin
    loop
        dbms_output.put_line(i); 
        i := i+1;
        exit when(i > 10);
    end loop;
end;
/

类似java中while循环

declare
    i binary_integer := 1;
begin
    while i <= 10 loop
        dbms_output.put_line(i); 
        i := i+1;
    end loop;
end;
/

类似java中for循环

begin
    for i in 1..10 loop
        dbms_output.put_line(i); 
    end loop;
    for i in reverse 1..10 loop
        dbms_output.put_line(i); 
    end loop;
end;
/

异常处理(实际返回行数大于请求行数)

declare
    v_temp number(11);
begin
    select cid into v_temp
    from company
    where cname in ('百度','腾讯');
exception
    when too_many_rows then
        dbms_output.put_line('太多记录'); 
    when others then
        dbms_output.put_line('error');
end;
/

异常处理(没有找到数据)

declare
    v_temp number(4);
begin
    select cname into v_temp
    from company
    where cid = 6;
exception
    when no_data_found then
        dbms_output.put_line('没数据'); 
end;
/

记录错误信息表以及主键自增序列创建

create table errorlog
(
    id number primary key,
    errcode number,
    errmsg varchar(1024),
    errdate date
);
create sequence seq_errorlog_id start with 1 increment by 1;

将删除错误回滚并将出错误信息记录在错误信息表中

declare
    v_cid company.cid%type := 1;
    v_errcode errorlog.errcode%type;
    v_errmsg errorlog.errmsg%type;
begin
    delete from company where cid = v_cid;
exception
    when others then
        rollback;
        v_errcode := sqlcode;
        v_errmsg := sqlerrm;
        insert into errorlog values(seq_errorlog_id.nextval,v_errcode,v_errmsg,sysdate);
        commit;
end;
/

游标 CURSOR

CURSOR与“do...while”遍历表中数据

declare
    cursor c is
        select * from company;
    v_company c%rowtype;
begin
    open c;
        loop
            fetch c into v_company;
            exit when (c%notfound);
            dbms_output.put_line(v_company.cname); 
        end loop;
    close c;
end;
/

CURSOR与“while”遍历表中数据

declare
    cursor c is
        select * from company;
    v_company company%rowtype;
begin
    open c;
    fetch c into v_company;
        while (c%found) loop   
            dbms_output.put_line(v_company.cname);
            fetch c into v_company;
        end loop;
    close c;
end;
/

CURSOR与“for”遍历表中数据(for循环开始时cursor自动打开,循环结束时cursor自动关闭)

declare
    cursor c is
        select * from company;
begin
    for v_company in c loop
        dbms_output.put_line(v_company.cname);
    end loop; 
end;
/

带参数的游标

declare
    cursor c(v_cid company.cid%type, v_cname company.cname%type)
    is
        select * from company where cid = v_cid and cname = v_cname;
begin
    for v_company in c(1,'百度') loop
        dbms_output.put_line(v_company.cname); 
    end loop;
end;
/

可更新游标(一般游标用处是只读,而可更新游标可以更改)

declare
    cursor c
    is
        select * from company for update;
begin
    for v_company in c loop
        if(v_company.cname = '字节跳动') then
            update company set cname = 'gg' where current of c;
        end if;
    end loop;
    commit;
end;
/

存储过程PROCEDURE

简单存储过程创建

create or replace procedure p1
is
    cursor c 
    is
    select * from emp;
begin
    for v_emp in c loop
        if(v_emp.cid = 1) then
            dbms_output.put_line('百度1');
        elsif(v_emp.cid = 2) then
            dbms_output.put_line('阿里巴巴1');
        elsif(v_emp.cid = 3) then
            dbms_output.put_line('腾讯1');
        elsif(v_emp.cid = 4) then
            dbms_output.put_line('字节跳动1');
        else
            dbms_output.put_line('google1');
        end if; 
    end loop;
end;
/
-- 执行存储过程p1
execute p1;

带参数的存储过程创建

create or replace procedure p2(
    v_a in number,
    v_b in number,
    v_max out number,
    v_temp in out number
)
is
begin
    if(v_a > v_b) then
        v_max := v_a;
    else
        v_max := v_b;
    end if;
    v_temp := v_temp + 1;
end;
/

-- 执行p2
declare
    v_a number := 3;
    v_b number := 4;
    v_max number;
    v_temp number := 5;
begin
    p2(v_a, v_b, v_max, v_temp);
    dbms_output.put_line(v_max); 
    dbms_output.put_line(v_temp); 
end;
/

函数FUNCTION

create or replace function sal_tax(
    v_sal number
)
    return number
is
    v_rate number;
begin
    if(v_sal < 2000) then 
        v_rate := 0.1;
    elsif (v_sal < 3000) then
        v_rate := 0.2;
    else
        v_rate := 0.3;
    end if;
    return v_sal*v_rate;
end;
/

-- 执行函数sal_tax select sal_tax(
3000) from company;

触发器TRIGGER

-- 用户对员工表的操作日志表
create table emp_log
(
    ename varchar2(20),
    eaction varchar2(20),
    etime date
);

-- 创建触发器,将用户对emp表的增删改操作记录插入emp_log表中
create or replace trigger trig
    after insert or delete or update on emp (for each row)
begin
    if inserting then
        insert into emp_log values(user, 'insert', sysdate);
    elsif updating then
        insert into emp_log values(user, 'update', sysdate);
    elsif deleting then
        insert into emp_log values(user, 'delete', sysdate);
    end if;
end;
/

update emp set cid = 4 where ename = 'rose';
原文地址:https://www.cnblogs.com/JimKing/p/9418272.html