存储过程

1. 存储过程优点[摘录]

    a. 存储过程可以使得程序执行效率更高、安全性更好,因为过程建立之后已经编译并且储存到数据库,直接写sql就需要先分析再执行因此过程效率更高,直接写sql语句会带来安全性问题,如:sql注入

    b. 建立过程不会很耗系统资源,因为过程只是在调用才执行。

    c. 存储过程可以用于降低网络流量,存储过程代码直接存储于数据库中,所以不会产生大量T-sql语句的代码流量。

2. 包【含包头与包体】

    a. 包头

        包含对外可用的函数的声明、存储过程的声明、变量的声明等

    b. 包体

        包含包的实现,如函数的实现、过程的实现等

3. 包头的定义

create or replace packge PKG_USERS is
-- Public variable declarations
type userCursor is ref cursor;//定义一个游标变量,用于存储过程和函数返回结果集时使用,因为PL/SQL不允许存储过程或函数直接返回结果集,但可以返回类型变量, 于是引用游标的类型变量作为输出参数或返回值就应运而生了
-- Public function and procedure declarations
procedure GetUserByUid(p_Uid in integer, v_cursor out userCursor);
procedure sp_User_Search(p_LoginEmail in nvarchar2, p_Mobile in nvarchar2, v_cursor out userCursor);
...
end PKG_USERS;

4. 包体的定义

create or replace packge body PKG_USERS is
-- Function and procedure implementations
procedure GetUserByUid(p_Uid in integer, v_cursor out userCursor)
is
begin
open v_cursor for

select user_id, user_name, login_email from tbl_user 
where user_id = p_Uid

end GetUserByUid;

end PKG_USERS;

----open cursor for select 作用是:打开一个游标,游标的内容为查询的结果集

如:open cursor for select * from tbl_user 目的就是遍历tbl_user这个表中的每条数据

5. 在包外声明一个存储过程

create or replace procedure sp_user_add
(
   p_LoginEmail in nvarchar2,
   p_FullName   in nvarchar2,
   p_Gender     in integer,
   v_UserID     out integer
)
is
begin

insert into tbl_user(LOGIN_EMAIL, FULLNAME, GENDER)
values(p_LoginEmail, p_FullName, p_Gender)

select tbl_user_seq.currval into v_UserID from dual;

end sp_user_add;

select tbl_user_seq.currval into v_UserID from dual 的作用:

把表tbl_user_seq中的当前值赋给v_UserID,tbl_user_seq是为tbl_user建立的sequence表,在oracle中sequence就是所谓的序列号,每次取的时候它会自动增加,一般用在需要按序列号排序的地方,由于在设计tbl_user时把v_UserID列设计成了自增列,所以需要再为tbl_user再设计一个sequence表,语法如下:

-- Create sequence 
create sequence tbl_user_seq
minvalue 1
maxvalue 999999999999999999999999999
start with 9265
increment by 1
cache 20;

一旦定义好了tbl_user_seq之后,就可以访问currval和nextval了
currval = 返回sequence的当前值
nextval = 返回sequence的当前值+increment by值

到此,还得为tbl_user再建一个触发器,语法如下:

create OR replace trigger tbl_user_trg before insert on tbl_user
for each row
begin
  <<COLUMN_SEQUENCES>>
  begin
    if :new.USER_ID is null then       //USER_ID为列名
      select tbl_user_seq.nextval into :new.USER_ID from dual;
    end if;
  end COLUMN_SEQUENCES;
end;

这样,在对tbl_user进行插入操作时会先触发这个触发器,这个触发器的作用就是从tbl_user_seq表中取出自增值赋给USER_ID

6. 关于dual表【网上摘录】

    dual是一个虚拟表,用来构成select的语法规则,oracle保证dual里面永远只有一条记录。我们可以用它来做很多事情,如下:

    a. 查看当前用户,可以在 SQL Plus中执行下面语句 select user from dual;

    b. 用来调用系统函数

       select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;--获得当前系统时间

       select SYS_CONTEXT('USERENV','TERMINAL') from dual;--获得主机名

       select SYS_CONTEXT('USERENV','language') from dual;--获得当前 locale

       select dbms_random.random from dual;--获得一个随机数

    c. 得到序列的下一个值或当前值,用下面语句

    select your_sequence.nextval from dual; //获得序列your_sequence的下一个值

    select your_sequence.currval from dual; //获得序列your_sequence的当前值

    d. 可以用做计算器 select 7*9 from dual;

7. 动态sql

例子:根据email和mobile联合查询

create or replace procedure sp_user_search
(
   p_Email in nvarchar2,
   p_Mobile     in nvarchar2,
   v_cursor    OUT PCKG_CURSOR.coursor_type
)
is
searchStr varchar2(1000);//定义一个varchar2型变量,用于拼装sql
begin

searchStr :='select user_id, login_email, gender, mobile, status from tbl_user where status<>8';

if(p_LoginEmail is not null) then
searchStr := searchStr || 'and login_email like ''%' || p_Email || '%'' ';
end if;

if(p_Mobile is not null) then
searchStr := searchStr || 'and mobile = ''' || p_Mobile || ''' ';
end if;

open v_cursor for searchStr;

end sp_user_search;
原文地址:https://www.cnblogs.com/notebook2011/p/2931634.html