oracle 的遍历语法,oracle pl/sql之pl/sql语法

一.pl/sql基础

pl/sql分匿名块和命名块.

命名块:存储过程,函数,触发器,包等.

pl/sql语句块分3部分:

(1)声明部分

(2)可执行部分

(3)异常处理部分

其中可执行部分是语句块中唯一要求必须存在的部分,声明部分和异常处理部分是可选的。

1.匿名块语法:

DECLARE

declaration statements

BEGIN

executable statements

EXCEPTION

exception-handing statements

END;

2.声明变量

语法:

identifier [CONSTANT] datatype [NOT NULL] [:= value | DEFAULT expr]

声明变量方法1:

declare

v_first_name varchar2(50);

c_count   constant number :=0;  ---常量

v_hiredate  date;

v_valid   BOOLEAN NOT NULL DEFAULT TRUE;

声明变量方法1:

declare

v_ename emp.ename%type;

v_sal emp.sal%type;

//显示雇员的姓名,工资,个人所得税set serveroutput on;

declare

v_ename varchar2(20);

v_sal number(6,2);

c_tax_rate constant number(3,2) :=0.06; ---税率

v_tax_sal number(6,2);

begin

select ename,sal into v_ename,v_sal from emp where empno = &no;

v_tax_sal := v_sal * c_tax_rate; ---赋值

dbms_output.put_line('v_ename: ' || v_ename);

dbms_output.put_line('v_sal: ' || v_sal);

dbms_output.put_line('v_tax_sal: ' || v_tax_sal);

end;

3.标识符的命名规则

(1)定义变量,建议用v_,如v_ename

(2)定义常量,建议用c_,如c_tax_rate

(3)定义游标,建议用_cursor作为后缀,如emp_cursor

(4)定义表类型,建议用_table_type作为后缀,如sal_table_type;

(5)定义表变量,建议用_table作为后缀,例如sal_table;

4.PL/SQL编译过程步骤

编译过程包括语法检查,绑定以及为代码生成。语法检查涉及检查PL/SQL代码中的编译错误。在纠正语法错误之后,会给每个变量分配内存地址,以保存ORACLE数据,这个过程成为绑定。接下来,会产生PL/SQL语句块的伪代码,伪代码是PL/SQL引擎的指令列表,对于命名语句块,伪代码会存储在数据库中,并在程序下一次执行时使用。

5.替代变量

在匿名PL/SQL块中接受输入参数使用&或者&&作为替代变量

6.初始化变量用select into语法//求emp表中的平均工资

SQL> set serveroutput on;

SQL>

SQL> declare

2 v_avg_sal number(6,2);

3 begin

4 select avg(sal) into v_avg_sal from emp;

5 dbms_output.put_line('v_avg_sal: ' || v_avg_sal);

6 end;

7 / ---表示执行

v_avg_sal: 2530.88

PL/SQL procedure successfully completed.

二.控制语句

7.if语句

if语法:

IF condition THEN

statements;

[ELSIF condition THEN

statements;]

[ELSE

statements;

]

END IF;

//如果工资小于2000,把雇员的薪水加薪50setserveroutput on;

declare

v_sal emp.sal%type;

begin

select sal into v_sal from emp where lower(ename)=lower('&name');

if v_sal <2000 then

update emp set sal=sal+50 where lower(ename)=lower('&name');

end if;

end;

//如果job=PRESIDENT,sal=sal+200

job=MANAGER ,sal=sal+1000

other ,sal=sal+100setserveroutput on;

declare

v_job emp.job%type;

v_empno emp.empno%type;

begin

select job,empno into v_job,v_empno from emp where empno=&no;

if v_job='PRESIDENT' then

update emp set sal=sal+200 where empno=v_empno;

elsif v_job='MANAGER' then

update emp setsal=sal+1000 where empno=v_empno;

else

update emp set sal=sal+100 where empno=v_empno;

endif;

commit;

end;

8.循环语句

//loop循环

loop

statements;

exit [when condition];

end loop;

//例子create table tmp01 (id int);

declare i int :=1;

begin

loop

insert into tmp01 values (i);

commit;

exit when i >100;

i := i+1;

end loop;

end;

//while循环

while condition loop

statement1;

statement2;

......

end loop;

//例子declare i number :=1;

begin

while i <100 loop

insert into tmp01 values (i);

i := i+1;

end loop;

commit;

end;

//FOR循环

for counter in [reverse] lower_bound .. upper_bound loop  ---counter变量不需要定义

statement1;

statement2;

......

end loop;

//例子begin

for i in 1..100 loop

insert into tmp01 values (i);

end loop;

commit;

end;

//用替代变量输入部门号,使用case语句判断条件更新雇员工资

部门号为10,雇员加薪10%

部门号为20,雇员加薪8%

部门号为30,雇员加薪15%

如果输入其他数字,则显示“该部门不存在”declare

v_deptno emp.deptno%type;

begin

v_deptno := &deptno;

case v_deptno

when 10 then

update emp set sal=sal*1.1 where deptno=v_deptno;

when 20 then

update emp set sal=sal*1.08 where deptno=v_deptno;

when 30 then

update emp set sal=sal*1.15 where deptno=v_deptno;

else

dbms_output.put_line('deptno not exists');

end case;

end;

9.SQL游标

当执行select,insert,update,delete时,oracle会为SQL语句分配相应的上下文区域(context area).oracle使用上下区域解析并执行相应的SQL语句,而游标就是指向上下文区域的指针。

游标包括隐式游标和显示游标。其中隐式游标也称为SQL游标,专门用于处理select into,insert,update,delete语句。显示游标用于处理多行select语句。

SQL游标属性:sql%found,sql%notfound,sql%rowcount,sql%isopen等

(1)sql%isopen:用于确定SQL游标是否打开。

(2)sql%found:用于确定SQL语句是否执行成功。

(3)sql%notfound:用于确定SQL语句是否执行成功。

(4)sql%rowcount:用于返回SQL语句所作用的总计行数。

//例子1set serveroutput on;

declare

v_deptno emp.deptno%type := &no;

begin

update emp set sal = sal*1.05 where deptno=v_deptno;

if sql%notfound then

dbms_output.put_line('deptno is not exist.');

else

dbms_output.put_line('sql execute successful.');

end if;

end;

//例子2set serveroutput on;

declare

v_deptno emp.deptno%type := &no;

begin

update emp set sal = nvl(sal,0)*1.05 where deptno=v_deptno;

dbms_output.put_line('have '|| sql%rowcount || ' row have change.');

if sql%notfound then

dbms_output.put_line('deptno is not exist.');

else

dbms_output.put_line('sql execute successful.');

end if;

end;

10.例子

用替代变量输入客户名(不区分大小写)和所在城市,并修改客户所在城市,如果客户不在,则显示“该客户不在”

客户名:yangry

city:henan+---创建表

create table customer(customer_id number not null,customer_name varchar2(50),

city_name varchar2(50) ,constraint pk_customer primary key(customer_id));

---代码

set serveroutput on;

declare

v_name customer.customer_name%type;

v_city customer.city_name%type;

begin

v_name := '&customer_name';

v_city := '&city_name';

update customer set city_name=v_city where upper(customer_name)=upper(v_name);

if sql%notfound then

dbms_output.put_line('customer is not exist.');

end if;

commit;

end;

三.PL/SQL集合

(1)索引表(Associative arrays, also known as index-by tables)

(2)嵌套表

(3)变长数组

用于处理多行单列数据

(4)PL/SQL记录表

处理多行多列数据

1.pl/sql记录

TYPE type_name IS RECORD(

field_declaration1[,field_declaration2]...

);

identifier type_name;

type_name:记录类型的名称(IS RECORD 表示记录类型)

field_declaration:记录成员的定义,多个记录成员之间用逗号(,)隔开.

identifier:指定记录变量名

定义pl/sql记录方法1:

type emp_record_type is record (

names emp.ename%type,

salary emp.sal%type,

dno emp.deptno%type

);

---emp_record是基于记录类型emp_record_type所定义的记录变量

emp_record emp_record_type;

定义pl/sql记录方法2:

%rowtype属性可以基于表或者视图定义记录变量

identified table_name%rowtype;

or

identified view_name%rowtype;

dept_record dept%rowtype;

----ename,sal,dno

---替代变量用eno---empno

dbms_output.put_line(emp_record.names);

set serveroutput on;

declare

type emp_record_type is record(

names emp.ename%type,

salary emp.sal%type,

dno emp.deptno%type

);

emp_record emp_record_type;

begin

select ename,sal,deptno into emp_record from emp where empno=&no;

dbms_output.put_line('names: ' || emp_record.names);

dbms_output.put_line('salary: ' || emp_record.salary);

dbms_output.put_line('dno: ' || emp_record.dno);

end;

---在select into语句中使用记录成员set serveroutput on;

declare

type emp_record_type is record(

names emp.ename%type,

salary emp.sal%type,

dno emp.deptno%type

);

emp_record emp_record_type;

begin

select ename,sal,deptno into emp_record.names,emp_record.salary,emp_record.dno from emp where empno=&no;

dbms_output.put_line('names: ' || emp_record.names);

dbms_output.put_line('salary: ' || emp_record.salary);

dbms_output.put_line('dno: ' || emp_record.dno);

end;

---在insert的values子句中使用记录变量/记录成员,向dept表中插入一条数据set serveroutput on;

declare

dept_record dept%rowtype;

begin

dept_record.deptno :=&no;

dept_record.dname := &names;

dept_record.loc :=&city;

---insert into dept(deptno,dname,loc) values();

insert into dept values dept_record;

end;

2.嵌套表(nested table)

嵌套表一种用于处理PL/SQL数组的数据类型。嵌套表的元素下标从1开始,并且元素个数没有限制。

语法:

table type_name is table of element_type;

identifier type_name;

type_name指嵌套表的类型名。

element_type指嵌套表元素的数据类型。

identifier指嵌套表变量。

使用嵌套表元素时,需要先使用构造方法初始化嵌套表

declare

table emp_table_type is table of emp.ename%type;

emp_table emp_table_type := emp_table_type('c','c');

//emp表中雇员姓名set serveroutput on;

declare

type ename_table_type is table of emp.ename%type;

ename_table ename_table_type;

begin

ename_table :=ename_table_type('y1','y2');

select ename into ename_table(1) from emp where empno=&no;

dbms_output.put_line('employee name: ' || ename_table(1));

end;

3.集合方法

COUNT, DELETE, EXISTS, EXTEND, FIRST, LAST, LIMIT, NEXT, PRIOR, and TRIM

4.批量绑定

forall语法

forall index in lower_bound..upper_bound

sql_statement;

index隐含定义的×××变量(作为集合元素下标使用)

lower_bound|upper_bound集合元素的上界和下界。

create table tmp01(id number primary key, name varchar(10));

---codedeclare

type id_table_type is table of number index by binary_integer;

type name_table_type is table of varchar2(10) index by binary_integer;

id_table id_table_type ;

name_table name_table_type ;

start_time number;

end_time number;

begin

for i in 1..5000 loop

id_table(i):=i;

name_table(i):='name' || i;

end loop;

start_time := DBMS_UTILITY.GET_TIME;

forall i in 1..5000

insert into tmp01 values(id_table(i),name_table(i));

commit;

end_time := DBMS_UTILITY.GET_TIME;

dbms_output.put_line('total time is: ' || to_char((end_time-start_time)/100));

end;

5.索引表

---语法

TYPE type_name IS TABLE OF element_type [NOT NULL] INDEX BY key_type;

indentifer type_name;

type_name指定用户自定义数据类型名称

element_type 指定索引表元素的数据类型

key_type指定索引表元素下标的数据类型(varchar2,binary_integer,pls_integer等)

indentifer指定索引表变量

索引表的下标可以为负值,而且元素个数没有限制。

---codeset serveroutput on;

declare

type ename_table_type is table of emp.ename%type index by binary_integer;

ename_table ename_table_type;

begin

select ename into ename_table(1) from emp where empno=&no;

dbms_output.put_line('employee name : ' || ename_table(1));

end;

---索引表中使用varchar2set serveroutput on;

declare

type city_table_type is table of number index by varchar2(10);

city_table city_table_type;

begin

city_table('zhouzq') := 1;

city_table('lidd') := 2;

city_table('lijian') := 3;

dbms_output.put_line('the first element: ' || city_table.first);

dbms_output.put_line('the last element: ' || city_table.last);

end;

6.游标

使用显示游标包括定义游标,打开游标,提取游标和关闭游标。

(1)定义游标

CURSOR cursor_name IS  select_statement;

(2)打开游标

OPEN cursor_name;

(3)提取游标

---提取一行

FETCH cursor_name into var1,var2...;

---提取多行

FETCH cursor_name BULK COLLECT INTO collect1,collect2...[LIMIT rows];

---collect1用于指定接受游标的集合变量

(4)关闭游标

CLOSE cursor_name;

显示游标属性:%isopen,%found,%notfound,%rowcount

---显示游标中使用fetch...into

//提取雇员名,薪水set serveroutput on;

declare

cursor emp_cursor is select ename,sal from emp where deptno=10;

v_ename emp.ename%type;

v_salary emp.sal%type;

begin

open emp_cursor;

loop

fetch emp_cursor into v_ename,v_salary;

exit when emp_cursor%notfound;

dbms_output.put_line(v_ename || ' : ' || v_salary);

end loop;

end;

---显示游标中使用fetch...bulk collect into

###显示部门10的所有雇员名set serveroutput on;

declare

cursor ename_cursor is select ename from emp where deptno=10;

type ename_table_type is table of varchar2(10);

ename_table ename_table_type;

begin

open ename_cursor;

fetch ename_cursor bulk collect into ename_table;

for i in 1..ename_table.count loop

dbms_output.put_line(ename_table(i));

end loop;

close ename_cursor;

end;

---游标FOR循环

语法:

FOR record_name IN cursor_name loop

statement1;...

end loop;

cursor_name:已定义的游标名称

record_name:隐含定义的记录变量名

在执行循环体内容之前,oracle会隐含地打开游标,并且每循环一次提取一次数据,提取完所有数据后,会自动退出循环并隐含关闭游标。

---FOR循环游标set serveroutput on;

declare

cursor ename_cursor is select ename from emp;

begin

for cc_record in ename_cursor loop

dbms_output.put_line(ename_cursor%rowcount ||': ' || cc_record.ename);

end loop;

end;

---游标FOR循环中直接使用子查询set serveroutput on;

begin

for cc_record in (select ename from emp) loop

dbms_output.put_line( cc_record.ename);

end loop;

end;


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部