PLSQL语法介绍(有例子带注释)关键字: oracle/plsql/游标/存储过程/触发器--最简单的语句块set serveroutput on; //用于输出显示begindbms_output.put_line('HeloWorld');end;--一个简单的PL/SQL语句块declare //声明变量,必须 v_ 开头v_name varchar2(20);beginv_name := 'myname'; //变量的赋值格式dbms_output.put_line(v_name);end;--语句块的组成declarev_num number := 0;beginv_num := 2/v_num;dbms_output.put_line(v_num);exception //如果没有这部分,当出现异常的时候,就执行过不去when others thendbms_output.put_line('error');end;--变量声明的规则1): 变量名不能够使用保留字,如from、select等2): 第一个字符必须是字母3): 变量名最多包含30个字符4): 不要与数据库的表或者列同名5): 每一行只能声明一个变量--常用变量类型1): binary_integer: 整数,主要用来计数而不是用来表示字段类型2): number: 数字类型3): char: 定长字符串4): varchar2: 变长字符串5): date: 日期6): long: 长字符串,最长2GB7): boolean: 布尔类型,可以取值为 true、false和null--变量声明,可以使用 %type 属性declarev_empno number(4);v_empno2 emp.empno%type;//表示该变量的类型和emp表中的empno字段保持一致。
v_empno3 v_empno2%type;begindbms_output.put_line('Test');--Table变量类型 //类似于java中的数组declaretype type_table_emp_empno is table of emp.empno%type index by binary_integer; //声明一个类型v_empnos type_table_emp_empno;beginv_empnos(0) := 100;v_empnos(2) := 200;v_empnos(-1):= 300;dbms_output.put_line(v_empnos(-1));end;--Record变量类型 //类似于java中的类,可以表示一整条记录declaretype type_record_dept is record(deptno dept.deptno%type,dname dept.dname%type,loc dept.loc%type);v_temp type_record_dept;beginv_temp.deptno := 50;v_temp.dname := 'aaa';v_temp.loc := 'bj';dbms_output.put_line(v_temp.deptno || '' || v_temp.dname); end;不过当表增加了一个字段之后它就不管用了,可以选用下面的这种: %rowtype --使用%rowtype声明Record类型变量declarev_temp dept%rowtype;beginv_temp.deptno := 50;v_temp.dname := 'aaa';v_temp.loc := 'bj';dbms_output.put_line(v_temp.deptno || '' || v_temp.dname);--SQL语句的运用1:declarev_ename emp.ename%type;v_sal emp.sal%type;beginselect ename,sal into v_ename,v_sal from emp where empno = 7369;//必须返回记录,并且只能返回一条dbms_output.put_line(v_ename || '' || v_sal);end;2:declarev_emp emp%rowtype;beginselect * into v_emp from emp where empno = 7396;dbms_output.put_line(v_emp.ename);end;3:declarev_deptno dept.deptno%type := 50;v_dname dept.dname%type := 'aaa';v_loc dept.loc%type := 'bj';begininsert into dept2 values (v_deptno,v_dname,v_loc); //insert、delete、update和sql是一样的,只是可以用变量commit;end;4:declarev_deptno emp2.deptno%type := 10;v_count number;beginupdate emp2 set sal = sal/2 where deptno = v_deptno;dbms_output.put_line(sql%rowcount || '条记录被影响');commit;end;sql%rowcount 表示:刚执行的最后一句sql影响到了多少条记录--执行DDL语句beginexecute immediate 'create table T (nnn varchar2(20) default ''aaa'')';end;--if语句--取出7369的薪水,如果<1200,则输出'low',如果<2000则输出'middle',否则'high'declarev_sal emp.sal%type;beginselect sal into v_sal from emp where empno = '7369'; if(v_sal < 1200) thendbms_output.put_line('low');elsif(v_sal < 2000) thendbms_output.put_line('middle');elsedbms_output.put_line('high');end if;end;--循环(1):相当于 do .. while 循环declarei binary_integer := 1;beginloopdbms_output.put_line(i);i := i + 1;exit when (i >= 11); //循环结束的条件end loop;end;(2):while循环declarej binary_integer := 1;beginwhile j < 11 loopdbms_output.put_line(j);j := j + 1;end loop;end;(3):for循环beginfor k in 1..10 loopdbms_output.put_line(k);end loop;for k in reverse 1..10 loop //表示 k 的值从 10 到 1 dbms_output.put_line(k);end loop;end;--错误处理 (too_many_rows、no_data_found 等等)declarev_temp number(4);beginselect empno into v_temp from emp where empno = 10; exceptionwhen too_many_rows thendbms_output.put_line('太多记录了');when no_data_found thendbms_output.put_line('没数据');when others thendbms_output.put_line('error');end;--将错误信息存储到一张日志表中(1):create table errorlog(id number primary key,errcode number,errmsg varchar2(1024),errdate date);(2):create sequence seq_errorlog_id start with 1 increment by 1;(3):declarev_deptno dept.deptno%type := 10;v_errcode number;v_errmsg varchar2(1024);begindelete from dept where deptno = v_deptno;commit;exceptionwhen others thenrollback;v_errcode := SQLCODE; //是关键字,错误代码v_errmsg := SQLERRM; //是关键字,错误信息insert into errorlogvalues(seq_errorlog_id.nextval,v_errcode,v_errmsg,sysdate); commit;end;--游标1:用游标取一条记录cursor c is //声明一个游标,这时候不会真正执行后面的查询语句,要等到打开游标的时候才执行select * from emp;v_emp c%rowtype;beginopen c;fetch c into v_emp;dbms_output.put_line(v_emp.ename);close c;end;2:结合循环取出多条记录(1):do..while循环declarecursor c isselect * from emp;v_emp c%rowtype;beginopen c;loopfetch c into v_emp;exit when (c%notfound); //当最近一次 fetch 没有返回记录dbms_output.put_line(v_emp.ename);end loop;close c;end;(2):while循环declarecursor c isselect * from emp;v_emp emp%rowtype;beginopen c;fetch c into v_emp;while (c%found) loopdbms_output.put_line(v_emp.ename);fetch c into v_emp;end loop;close c;end;(3):for循环declarecursor c isselect * from emp;for v_emp in c loop //for循环会自动打开和关闭游标,还会自动fetch..intodbms_output.put_line(v_emp.ename);end loop;end;--带参数的游标declarecursor c(v_deptno emp.deptno%type,v_job emp.job%type)isselect ename,sal from emp where deptno = v_deptno and job = v_job;beginfor v_temp in c (30,'clerk') loopdbms_output.put_line(v_temp.ename);end loop;end;--可更新的游标declarecursor cisselect * from emp2 for update;beginfor v_temp in c loopif(v_temp.sal < 2000) thenupdate emp2 set sal = sal * 2 where current of c;elsif(v_temp.sal = 5000) thendelete from emp2 where current of c;end if;end loop;commit;end;--存储过程存储过程:带有名字的PL/SQL的程序块,没有返回值create or replace procedure pis //用它代替了 declarecursor c isselect * from emp2 for update;beginfor v_emp in c loopif(v_emp.deptno = 10) thenupdate emp2 set sal = sal + 10 where current of c; elsif(v_emp.deptno = 20) thenupdate emp2 set sal = sal + 20 where current of c;elseupdate emp2 set sal = sal + 50 where current of c; end if;end loop;commit;end;上面的程序只是定义了一个存储过程,并没有真正执行。