- 浏览: 787782 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (981)
- javascript (102)
- java (212)
- JQuery (81)
- 幽默笑话 (2)
- 只言片语 (6)
- 开发小记 (283)
- Hibernate (17)
- DWR (4)
- SQL (10)
- spring-ibatis (8)
- linux (24)
- Struts1 (8)
- Struts2 (16)
- spring (42)
- Mybatis (16)
- css (18)
- servlet (8)
- jdbc (4)
- jsp (1)
- spring-jdbc (2)
- FreeMarker (2)
- MySQL (24)
- JQuery-Grid (7)
- jstl (5)
- 正则表达式 (1)
- 面试集锦 (86)
- unix (18)
- 开发工具 (23)
- ajax (5)
- webservice (4)
- log4j (3)
- oracle (15)
- extjs (14)
- 其他 (9)
- 优秀技术参考地址 (1)
- 性能 (3)
- 数据库 (25)
- 算法 (15)
- 设计模式 (10)
- Python (3)
- AIX (5)
- weblogic (1)
- shell (14)
- quartz (5)
- 图形文件FusionCharts (1)
- Websphere (4)
- 转载 (5)
- hadoop (1)
- highchart (24)
- perl (22)
- DB2 (7)
- JBoss (1)
- JQuery Easy UI (9)
- SpringMVC (5)
- ant (5)
- echart (9)
- log4J配置 (3)
- 多线程 (10)
- 系统架构 (7)
- nginx (3)
- loadrunner1 (1)
- 分布式 (1)
- Dubbo (1)
- Redis (2)
- JMS (4)
- 自动化测试 (3)
- Spring循环依赖的三种方式 (1)
- spring-boot (2)
- 高级测试 (9)
- github (2)
- sonar (1)
- docker (6)
- web前端性能优化 (1)
- spring-aop (6)
- rabbit (1)
- ELK (1)
- maven (1)
- minio (1)
最新评论
-
zengshaotao:
jstl1point0 写道很好啊,如果有带Session会话 ...
Nginx+Tomcat搭建高性能负载均衡集群 -
jstl1point0:
很好啊,如果有带Session会话的怎么搞呢
Nginx+Tomcat搭建高性能负载均衡集群
PL/SQL程序有以下优点:
软件生产效率很高;系统性能良好;系统资源利用率高(如:节省内存)
Sql基本的语法结构
Declare
/* 声明部分: 在此 声明PL/SQL用到的变量,类型及光标 */
begin
/* 执行部分: 过程及SQL 语句 , 即程序的主要部分 */
Exception
/* 执行异常部分: 错误处理 */
End;
定义部分: 定义将在执行部分调用的所有变量,常量,游标,和用户自定义的异常处理. 这部分可以没有.
执行部分: 包括对数据库进行操作的SQL语句,以及对语句进行组织,控制的PL/SQL语句。这部分在PL/SQL块中必须存在.
例外处理部分:可执行部分中的语句,在执行过程中出错或出现非正常现象时,所应做的相应处理. 这部分可以没有
第一次使用的变量必须在定义部分定义,只有定义过的变量才能在执行部分引用.需要注意的是块可以嵌套使用.
变量类型
类型 子类 说 明 范围 ORACLE限制
-------------------- ------------ ------------ ------------------------
Char character 定长字符串 032767 255
Rowid
Varchar2 varchar 可变字符串 032767 4000
Binary_integer 带符号整数,为整数计算优化性能
Number(p,s) Dec 小数, Number 的子类型
Double precision 高精度实数
Integer 整数, Number 的子类型
Int 整数, Number 的子类型
Numeric 与Number等价
Real 与Number等价
Small int 整数, 比 integer 小
Long 变长字符串,一般在PL/SQL中只能用到 32,767字节
Date 日期型
Boolean 布尔型, TRUE, 或 FALSE
ROWID 存放数据库行号
提示: 一般不要把变量名声明与表中字段名完全一样,如果这样可能得到不正确的结果.
在 PL/SQL 语句中使用DBMS_OUTPUT.PUT_LINE 语句输出变量或字串.
Begin dbms_output.put_line(‘输出字符串');end;
在PL/SQL块中引用的所有标识符,都必须在PL/SQL块的定义部分中明确定义。在定义一个标识符时,首先要为其确定一个名字,其次是确定它是变量还是常量,然后是它的数据类型、是否允许为空值(NULL),以及如果有初始值,其初始值是什么。具体的语法形式如下所示:
<标识符> [CONSTANT] <数据类型> [NO TNULL][:= | DEFAULT <PL/SQL表达式>];
同时,还要注意以下几点:
标识符的命名规则遵循所有SQL实体的命名规则。如果定义常量,必须加上关键字“CONSTANT”,而且定义常量时必须为其赋值。定义的变量不允许有空值出现时,必须使用关键字“NOT NULL”,并且为该变量赋初始值。为变量赋值时,使用赋值操作符
“:=”,或者,使用权用关键字“DEFAULT”。如果不为变量赋值,则其缺省的初始值为空值。
每行只能定义一个标识符。
DECLARE
n1 number(10,2);v1 varchar2(20) not null DEFAULT ‘天津’;
v2 varchar2(20):=‘天津’;v3 CONSTANT varchar2(20):=‘天津’;
v4 CONSTANT varchar2(20) DEFAULT ‘天津’;
使用%TYPE
可以将变量类型定义为与数据库中表的字段相同的类型,当字段的数据类型变化时则变量的类型也相应的变化。
DECLARE v1 xs_xx.xsid%TYPE;
使用%ROWTYPE可以将变量类型定义为与具有相同类型的数据库行。它将返回一个基于表定义的类型。DECLARE record1 XS_XX%ROWTYPE;
PL/SQL 程序中只能使用 DML 和 事务控制,不能使用 DDL 语句。在PL/SQL V2.1 以后的版本可以采用动态的方法来使用 DDL 语句。
DECLARE
V_empRecord emp%ROWTYPE;
V_empno emp.empno%TYPE;
Begin
Select * into V_empRecord From emp where emp.empno = '7369';
dbms_output.put_line(V_empRecord.empno||'|'||V_empRecord.ename);
select empno into V_empno from emp where empno = '7369';
dbms_output.put_line(V_empno);
END;
insert 语句可以包括 一个 select 语句,但要求选择列表要与插入列表相匹配。
DECLARE
V_empno emp.empno%TYPE;
BEGIN
SELECT test_seq1.NEXTVAL INTO V_empno from dual;
INSERT INTO emp(empno,ename)VALUES(V_empno,’Wang’);
End;
事务控制
事务(transaction)是一系列作为一个单元被成功或不成功执行的SQL语句。例如银行的事务:从一个帐号上汇出款到另一帐号上去(汇入):
begin
UPDATE accounts SET balance = balance – transaction_amount
WHERE account_no= from_acct;
UPDATE accounts SET balance = balance + transaction_amount
WHERE account_no = to_acct;
Commit;
Exception
when others then
rollback;End;
声明游标 CURSOR cursor_name IS select_statement;
DELCARE
CURSOR C_EMP IS SELECT empno,ename,salary FROM emp WHERE salary>2000
ORDER BY ename;
在游标定义中SELECT语句中不一定非要表,可以是视图,也可以从多个表或视图中选择列,甚至可以使用*来选择所有的列。使用游标中的值之前应该首先打开游标,打开游标初始化查询处理。打开游标的语法是: OPEN cursor_name,cursor_name是在声明部分定义的游标名,如OPEN C_EMP; 关闭游标 CLOSE cursor_name 。
从游标得到一行数据使用FETCH命令。每一次提取数据后,游标都指向结果集的下一行。语法如:FETCH cursor_name INTO variable[,variable,...] 。对于SELECT定义的游标的每一列,FETCH变量列表都应该有一个变量与之相对应,变量的类型也要相同
SET SERVERIUTPUT ON
DECLARE
v_ename EMP.ENAME%TYPE; v_salary EMP.SALARY%TYPE;
CURSOR c_emp IS SELECT ename,salary FROM emp;
FETCH c_emp INTO v_ename,v_salary;
DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary);
FETCH c_emp INTO v_ename,v_salary;
DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary);
CLOSE c_emp; END;
上段代码无疑是非常麻烦的,如果有多行返回结果,可以使用循环并用游标属性为结束循环的条件,以这种方式提取数据,程序的可读性和简洁性都大为提高,下面我们使用循环重新写上面的程序:
DECLARE
v_ename EMP.ENAME%TYPE;v_salary EMP.SAL%TYPE;
CURSOR c_emp IS SELECT ename, sal FROM emp;
BEGIN
OPEN c_emp;
LOOP
FETCH c_emp INTO v_ename, v_salary;
DBMS_OUTPUT.PUT_LINE('Salary of Employee ' || v_ename || ' is ' ||v_salary);
EXIT WHEN c_emp%NOTFOUND;
end loop;
END;
%ROWTYPE也可以用游标名来定义,这样的话就必须要首先声明游标:
DECLARE
CURSOR c_emp IS SELECT ename, sal FROM emp;
r_emp c_emp%ROWTYPE;
BEGIN
OPEN c_emp;
LOOP
FETCH c_emp INTO r_emp;
EXIT WHEN c_emp%NOTFOUND;
dbms_output.PUT_LINE('Salary of Employee '|| r_emp.ename || 'is'||r_emp.sal);
END LOOP;
CLOSE c_emp;
END;
与存储过程和函数相似,可以将参数传递给游标并在查询中使用。这对于处理在某种条件下打开游标的情况非常有用。它的语法如下:
CURSOR cursor_name[(parameter[,parameter],...)] IS select_statement;
与存储过程不同的是,游标只能接受传递的值,而不能返回值。参数只定义数据类型,没有大小。另外可以给参数设定一个缺省值,当没有参数值传递给游标时,就使用缺省值。
在打开游标时给参数赋值,语法如下:
OPEN cursor_name[value[,value]....];
declare
r_dept DEPT%ROWTYPE;
v_ename EMP.ENAME%TYPE;
v_salary EMP.SAL%TYPE;
v_tot_salary EMP.SAL%TYPE;
cursor c_dept is select * from dept order by deptno;
CURSOR c_emp(p_dept VARCHAR2) IS
SELECT ename, sal FROM emp WHERE deptno = p_dept ORDER BY ename;
BEGIN
OPEN c_dept;
LOOP
FETCH c_dept INTO r_dept;
EXIT WHEN c_dept%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Department:' ||r_dept.deptno ||'-'||r_dept.dname);
v_tot_salary := 0;
OPEN c_emp(r_dept.deptno);
LOOP
FETCH c_emp INTO v_ename, v_salary;
EXIT WHEN c_emp%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Name:' || v_ename || ' salary:' || v_salary);
v_tot_salary := v_tot_salary + v_salary;
END LOOP;
CLOSE c_emp;
DBMS_OUTPUT.PUT_LINE('Toltal Salary for dept:' || v_tot_salary);
END LOOP;
CLOSE c_dept;
END;
在大多数时候我们在设计程序的时候都遵循下面的步骤:
打开游标 开始循环 从游标中取值 检查那一行被返回 处理 关闭循环 关闭游标
可以简单的把这一类代码称为游标用于循环。但还有一种循环与这种类型不相同,这就是FOR循环,用于FOR循环的游标按照正常的声明方式声明,它的优点在于不需要显式的打开、关闭、取数据,测试数据的存在、定义存放数据的变量等等。游标FOR循环的语法如下:
FOR record_name IN
(corsor_name[(parameter[,parameter]...)] | (query_difinition)
LOOP statements END LOOP;
下面我们用for循环重写上面的例子:
DECLARE
CURSOR c_dept IS SELECT deptno, dname FROM dept ORDER BY deptno;
CURSOR c_emp(p_dept VARCHAR2) IS
SELECT ename, sal FROM emp WHERE deptno = p_dept ORDER BY ename;
v_tot_salary EMP.SAL%TYPE;
BEGIN
FOR r_dept IN c_dept LOOP
DBMS_OUTPUT.PUT_LINE('Department: ' || r_dept.deptno || '-'||r_dept.dname);
v_tot_salary := 0;
FOR r_emp IN c_emp(r_dept.deptno) LOOP
DBMS_OUTPUT.PUT_LINE('Name: ' || r_emp.ename || 'salary: '||r_emp.sal);
v_tot_salary := v_tot_salary + r_emp.sal;
END LOOP;
DBMS_OUTPUT.PUT_LINE('Toltal Salary for dept: ' || v_tot_salary);
END LOOP;
END;
在游标FOR循环中可以定义查询,由于没有显式声明,所以游标没有名字,记录名通过游标查询来定义。
DECLARE
v_tot_salary EMP.SAL%TYPE;
BEGIN
FOR r_dept(不定义)IN (SELECT deptno, dname FROM dept ORDER BY deptno) LOOP
DBMS_OUTPUT.PUT_LINE('Department:' || r_dept.deptno || '-'||r_dept.dname);
v_tot_salary := 0;
FOR r_emp IN (SELECT ename, sal FROM emp WHERE deptno = r_dept.deptno ORDER BY ename) LOOP
DBMS_OUTPUT.PUT_LINE('Name:' || r_emp.ename || ' salary:'||r_emp.sal);
v_tot_salary := v_tot_salary + r_emp.sal;
END LOOP;
DBMS_OUTPUT.PUT_LINE('Toltal Salary for dept:' || v_tot_salary);
END LOOP;
END;
DECLARE
n number(10);
BEGIN
n:=1;
insert into w_test1(bh,n) values('a',n);
DECLARE
n number(10);
BEGIN
insert into w_test1(bh,n) values('b',n);
n:=100;
insert into w_test1(bh,n) values('b',n);
END;
insert into w_test1(bh,n) values('a',n);
END;
CREATE TABLE W_TEST1(
BH VARCHAR2(2),
N NUMBER(10));
BH N
-- -----------
a 1
b
b 100
a 1
运算符
符号 用途
------------- ------------------------------------------
!= 不等于号
<> 不等于号
:= 赋值号
=> 关系号
.. 范围运算符
|| 字符连接符
提示: ELSIF 不能写成 ELSEIF
简单循环
declare
x number;
begin
x:= 0;
loop
x:=x+1;
dbms_output.put_line(to_char(x));
exit when x=10;
end loop;
end;
DECLARE
V_counter BINARY_INTEGER := 1;
Begin
LOOP
Inert into temp_table
Values( v_counter, ‘loop index’ );
V_counter := v_counter + 1;
If v_counter > 50 then
Exit;
End if ;
End loop;
End;
• WHILE 循环
declare
x number;
begin
x:= 1;
while x<10 loop
dbms_output.put_line(to_char(x)||’还小于10’);
x:= x+1;
end loop;
end;
• 数字式循环
For 循环计数器 in 下限 .. 上限 .
begin
for I in 1 .. 10 loop
dbms_output.put_line('in=' || to_char(I));
end loop;
end;
为提高应用程序的健壮性,开发人员必须考虑程序可能出现的各种错误,并进行相应的处理。
Oracle中异常分为预定义例外,非预定义例外和自定义例外三种
预定义异常是指由PL/SQL所提供的系统异常.当PL/SQL应用程序违反了Oralce规则或系统限制时,则会隐含的触发一个内部异常。
PL/SQL为开发人员提供了二十多个预定义异常
DECLARE
CURSOR emp_cursor IS SELECT ename,sal FROM emp;
BEGIN
OPEN emp_cursor;
FOR emp_record IN emp_cursor LOOP
DBMS_OUTPUT.PUT_LINE(emp_record.ename);
END LOOP;
EXCEPTION
WHEN CURSOR_ALREADY_OPEN THEN
DBMS_OUTPUT.PUT_LINE('游标已经打开.');
END;
BEGIN
UPDATE DEPT SET DEPTNO = 20 WHERE DEPTNO = 10;
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
DBMS_OUTPUT.PUT_LINE(‘deptno列上不能出现重复值’);
END;
DECLARE
CURSOR emp_cursor IS SELECT ename,sal FROM emp;
emp_record emp_cursor%ROWTYPE;
BEGIN
FETCH emp_cursor INTO emp_record;
CLOSE emp_cursor;
EXCEPTION
WHEN INVALID_CURSOR THEN
DBMS_OUTPUT.PUT_LINE('请检查游标是否已经打开.');
END;
DECLARE
V_SAL EMP.SAL%TYPE;
BEGIN
SELECT SAL INTO V_SAL FROM EMP WHERE LOWER(ENAME) = LOWER('simth');
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('');
END;
DECLARE
TYPE emp_array_type IS VARRAY(20) OF VARCHAR2(10);
emp_array emp_array_type;
BEGIN
emp_array:=emp_array_type('SCOTT','MARY');
DBMS_OUTPUT.PUT_LINE(emp_array(3));
EXCEPTION
WHEN SUBSCRIPT_BEYOND_COUNT THEN
DBMS_OUTPUT.PUT_LINE('下标越界.');end;
自定义异常与Oracle错误没有任何关联,它是开发人员为特定情况所定义的异常.
自定义异常必须显式触发.使用步骤如下:
定义异常 -> 显式触发异常 -> 引用异常
首先要在定义部分(DECLARE)定义异常,然后在执行部分(BEGIN)触发异常(RAISE语句),
最后在异常处理部分(EXCEPTION)捕捉处理.
DECLARE
E_NO_EMPLOYEE EXCEPTION;
BEGIN
UPDATE EMP SET DEPTNO = 10 WHERE EMPNO = 7369;
IF SQL%NOTFOUND THEN
RAISE E_NO_EMPLOYEE;
END IF;
EXCEPTION
WHEN E_NO_EMPLOYEE THEN
DBMS_OUTPUT.PUT_LINE(‘该雇员不存在!’);
END;
CREATE OR REPLACE PROCEDURE raise_comm(eno NUMBER,commission NUMBER)
IS v_comm emp.comm%TYPE;
BEGIN
SELECT comm INTO v_comm FROM emp WHERE empno=eno;
IF v_comm IS NULL THEN
RAISE_APPLICATION_ERROR(-20001,'该员工无补助.');
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('该雇员不存在.');
END;
过程
用于执行动作的子程序。过程可以有多个入口及出口参数
CREATE OR REPLACE PROCEDURE 过程名 (入口参数1 [in|out|in out]类型,入口参数[in|out|in out] 类型) as
变量1 类型 ;变量2 类型 ;
begin
语句;
exception
when 例外 then语句; end ;
in –只读,不能修改out-只写,不能读值in out 读写
创建一个过程,指定人的工资加100
create or replace procedure Dp_add_gz(v_grid varchar2) as
n_rec number;
begin
select count(1) into n_rec from dual
where exists (select 1 from emp where empno = v_grid);
if n_rec > 0 then
update emp set sal = sal + 100 where empno = v_grid;
end if;
exception
when others then
null;
end;
函数必须有RETURN子句,并且有一个函数返回值,其他和PROCEDUCE一样。
CREATE OR REPLACE FUNCTION 函数名 (入口参数1类型,入口参数 类型) return type is
变量1 类型 ;变量2 类型 ;
Begin 语句; return ;
exception when 例外 then 语句; end ;
return 语句
一个函数可以有多个return 语句,但是只有一个可以被执行。当在函数执行的过程中,有return出现时,其后面的语句就不会在被执行了。
return 的类型必须和定义的类型相一致。只能通过out参数返回多个数值,语法和PROCEDUCE一样。省缺参数:同PRECEDUCE一样
软件生产效率很高;系统性能良好;系统资源利用率高(如:节省内存)
Sql基本的语法结构
Declare
/* 声明部分: 在此 声明PL/SQL用到的变量,类型及光标 */
begin
/* 执行部分: 过程及SQL 语句 , 即程序的主要部分 */
Exception
/* 执行异常部分: 错误处理 */
End;
定义部分: 定义将在执行部分调用的所有变量,常量,游标,和用户自定义的异常处理. 这部分可以没有.
执行部分: 包括对数据库进行操作的SQL语句,以及对语句进行组织,控制的PL/SQL语句。这部分在PL/SQL块中必须存在.
例外处理部分:可执行部分中的语句,在执行过程中出错或出现非正常现象时,所应做的相应处理. 这部分可以没有
第一次使用的变量必须在定义部分定义,只有定义过的变量才能在执行部分引用.需要注意的是块可以嵌套使用.
变量类型
类型 子类 说 明 范围 ORACLE限制
-------------------- ------------ ------------ ------------------------
Char character 定长字符串 032767 255
Rowid
Varchar2 varchar 可变字符串 032767 4000
Binary_integer 带符号整数,为整数计算优化性能
Number(p,s) Dec 小数, Number 的子类型
Double precision 高精度实数
Integer 整数, Number 的子类型
Int 整数, Number 的子类型
Numeric 与Number等价
Real 与Number等价
Small int 整数, 比 integer 小
Long 变长字符串,一般在PL/SQL中只能用到 32,767字节
Date 日期型
Boolean 布尔型, TRUE, 或 FALSE
ROWID 存放数据库行号
提示: 一般不要把变量名声明与表中字段名完全一样,如果这样可能得到不正确的结果.
在 PL/SQL 语句中使用DBMS_OUTPUT.PUT_LINE 语句输出变量或字串.
Begin dbms_output.put_line(‘输出字符串');end;
在PL/SQL块中引用的所有标识符,都必须在PL/SQL块的定义部分中明确定义。在定义一个标识符时,首先要为其确定一个名字,其次是确定它是变量还是常量,然后是它的数据类型、是否允许为空值(NULL),以及如果有初始值,其初始值是什么。具体的语法形式如下所示:
<标识符> [CONSTANT] <数据类型> [NO TNULL][:= | DEFAULT <PL/SQL表达式>];
同时,还要注意以下几点:
标识符的命名规则遵循所有SQL实体的命名规则。如果定义常量,必须加上关键字“CONSTANT”,而且定义常量时必须为其赋值。定义的变量不允许有空值出现时,必须使用关键字“NOT NULL”,并且为该变量赋初始值。为变量赋值时,使用赋值操作符
“:=”,或者,使用权用关键字“DEFAULT”。如果不为变量赋值,则其缺省的初始值为空值。
每行只能定义一个标识符。
DECLARE
n1 number(10,2);v1 varchar2(20) not null DEFAULT ‘天津’;
v2 varchar2(20):=‘天津’;v3 CONSTANT varchar2(20):=‘天津’;
v4 CONSTANT varchar2(20) DEFAULT ‘天津’;
使用%TYPE
可以将变量类型定义为与数据库中表的字段相同的类型,当字段的数据类型变化时则变量的类型也相应的变化。
DECLARE v1 xs_xx.xsid%TYPE;
使用%ROWTYPE可以将变量类型定义为与具有相同类型的数据库行。它将返回一个基于表定义的类型。DECLARE record1 XS_XX%ROWTYPE;
PL/SQL 程序中只能使用 DML 和 事务控制,不能使用 DDL 语句。在PL/SQL V2.1 以后的版本可以采用动态的方法来使用 DDL 语句。
DECLARE
V_empRecord emp%ROWTYPE;
V_empno emp.empno%TYPE;
Begin
Select * into V_empRecord From emp where emp.empno = '7369';
dbms_output.put_line(V_empRecord.empno||'|'||V_empRecord.ename);
select empno into V_empno from emp where empno = '7369';
dbms_output.put_line(V_empno);
END;
insert 语句可以包括 一个 select 语句,但要求选择列表要与插入列表相匹配。
DECLARE
V_empno emp.empno%TYPE;
BEGIN
SELECT test_seq1.NEXTVAL INTO V_empno from dual;
INSERT INTO emp(empno,ename)VALUES(V_empno,’Wang’);
End;
事务控制
事务(transaction)是一系列作为一个单元被成功或不成功执行的SQL语句。例如银行的事务:从一个帐号上汇出款到另一帐号上去(汇入):
begin
UPDATE accounts SET balance = balance – transaction_amount
WHERE account_no= from_acct;
UPDATE accounts SET balance = balance + transaction_amount
WHERE account_no = to_acct;
Commit;
Exception
when others then
rollback;End;
声明游标 CURSOR cursor_name IS select_statement;
DELCARE
CURSOR C_EMP IS SELECT empno,ename,salary FROM emp WHERE salary>2000
ORDER BY ename;
在游标定义中SELECT语句中不一定非要表,可以是视图,也可以从多个表或视图中选择列,甚至可以使用*来选择所有的列。使用游标中的值之前应该首先打开游标,打开游标初始化查询处理。打开游标的语法是: OPEN cursor_name,cursor_name是在声明部分定义的游标名,如OPEN C_EMP; 关闭游标 CLOSE cursor_name 。
从游标得到一行数据使用FETCH命令。每一次提取数据后,游标都指向结果集的下一行。语法如:FETCH cursor_name INTO variable[,variable,...] 。对于SELECT定义的游标的每一列,FETCH变量列表都应该有一个变量与之相对应,变量的类型也要相同
SET SERVERIUTPUT ON
DECLARE
v_ename EMP.ENAME%TYPE; v_salary EMP.SALARY%TYPE;
CURSOR c_emp IS SELECT ename,salary FROM emp;
FETCH c_emp INTO v_ename,v_salary;
DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary);
FETCH c_emp INTO v_ename,v_salary;
DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary);
CLOSE c_emp; END;
上段代码无疑是非常麻烦的,如果有多行返回结果,可以使用循环并用游标属性为结束循环的条件,以这种方式提取数据,程序的可读性和简洁性都大为提高,下面我们使用循环重新写上面的程序:
DECLARE
v_ename EMP.ENAME%TYPE;v_salary EMP.SAL%TYPE;
CURSOR c_emp IS SELECT ename, sal FROM emp;
BEGIN
OPEN c_emp;
LOOP
FETCH c_emp INTO v_ename, v_salary;
DBMS_OUTPUT.PUT_LINE('Salary of Employee ' || v_ename || ' is ' ||v_salary);
EXIT WHEN c_emp%NOTFOUND;
end loop;
END;
%ROWTYPE也可以用游标名来定义,这样的话就必须要首先声明游标:
DECLARE
CURSOR c_emp IS SELECT ename, sal FROM emp;
r_emp c_emp%ROWTYPE;
BEGIN
OPEN c_emp;
LOOP
FETCH c_emp INTO r_emp;
EXIT WHEN c_emp%NOTFOUND;
dbms_output.PUT_LINE('Salary of Employee '|| r_emp.ename || 'is'||r_emp.sal);
END LOOP;
CLOSE c_emp;
END;
与存储过程和函数相似,可以将参数传递给游标并在查询中使用。这对于处理在某种条件下打开游标的情况非常有用。它的语法如下:
CURSOR cursor_name[(parameter[,parameter],...)] IS select_statement;
与存储过程不同的是,游标只能接受传递的值,而不能返回值。参数只定义数据类型,没有大小。另外可以给参数设定一个缺省值,当没有参数值传递给游标时,就使用缺省值。
在打开游标时给参数赋值,语法如下:
OPEN cursor_name[value[,value]....];
declare
r_dept DEPT%ROWTYPE;
v_ename EMP.ENAME%TYPE;
v_salary EMP.SAL%TYPE;
v_tot_salary EMP.SAL%TYPE;
cursor c_dept is select * from dept order by deptno;
CURSOR c_emp(p_dept VARCHAR2) IS
SELECT ename, sal FROM emp WHERE deptno = p_dept ORDER BY ename;
BEGIN
OPEN c_dept;
LOOP
FETCH c_dept INTO r_dept;
EXIT WHEN c_dept%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Department:' ||r_dept.deptno ||'-'||r_dept.dname);
v_tot_salary := 0;
OPEN c_emp(r_dept.deptno);
LOOP
FETCH c_emp INTO v_ename, v_salary;
EXIT WHEN c_emp%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Name:' || v_ename || ' salary:' || v_salary);
v_tot_salary := v_tot_salary + v_salary;
END LOOP;
CLOSE c_emp;
DBMS_OUTPUT.PUT_LINE('Toltal Salary for dept:' || v_tot_salary);
END LOOP;
CLOSE c_dept;
END;
在大多数时候我们在设计程序的时候都遵循下面的步骤:
打开游标 开始循环 从游标中取值 检查那一行被返回 处理 关闭循环 关闭游标
可以简单的把这一类代码称为游标用于循环。但还有一种循环与这种类型不相同,这就是FOR循环,用于FOR循环的游标按照正常的声明方式声明,它的优点在于不需要显式的打开、关闭、取数据,测试数据的存在、定义存放数据的变量等等。游标FOR循环的语法如下:
FOR record_name IN
(corsor_name[(parameter[,parameter]...)] | (query_difinition)
LOOP statements END LOOP;
下面我们用for循环重写上面的例子:
DECLARE
CURSOR c_dept IS SELECT deptno, dname FROM dept ORDER BY deptno;
CURSOR c_emp(p_dept VARCHAR2) IS
SELECT ename, sal FROM emp WHERE deptno = p_dept ORDER BY ename;
v_tot_salary EMP.SAL%TYPE;
BEGIN
FOR r_dept IN c_dept LOOP
DBMS_OUTPUT.PUT_LINE('Department: ' || r_dept.deptno || '-'||r_dept.dname);
v_tot_salary := 0;
FOR r_emp IN c_emp(r_dept.deptno) LOOP
DBMS_OUTPUT.PUT_LINE('Name: ' || r_emp.ename || 'salary: '||r_emp.sal);
v_tot_salary := v_tot_salary + r_emp.sal;
END LOOP;
DBMS_OUTPUT.PUT_LINE('Toltal Salary for dept: ' || v_tot_salary);
END LOOP;
END;
在游标FOR循环中可以定义查询,由于没有显式声明,所以游标没有名字,记录名通过游标查询来定义。
DECLARE
v_tot_salary EMP.SAL%TYPE;
BEGIN
FOR r_dept(不定义)IN (SELECT deptno, dname FROM dept ORDER BY deptno) LOOP
DBMS_OUTPUT.PUT_LINE('Department:' || r_dept.deptno || '-'||r_dept.dname);
v_tot_salary := 0;
FOR r_emp IN (SELECT ename, sal FROM emp WHERE deptno = r_dept.deptno ORDER BY ename) LOOP
DBMS_OUTPUT.PUT_LINE('Name:' || r_emp.ename || ' salary:'||r_emp.sal);
v_tot_salary := v_tot_salary + r_emp.sal;
END LOOP;
DBMS_OUTPUT.PUT_LINE('Toltal Salary for dept:' || v_tot_salary);
END LOOP;
END;
DECLARE
n number(10);
BEGIN
n:=1;
insert into w_test1(bh,n) values('a',n);
DECLARE
n number(10);
BEGIN
insert into w_test1(bh,n) values('b',n);
n:=100;
insert into w_test1(bh,n) values('b',n);
END;
insert into w_test1(bh,n) values('a',n);
END;
CREATE TABLE W_TEST1(
BH VARCHAR2(2),
N NUMBER(10));
BH N
-- -----------
a 1
b
b 100
a 1
运算符
符号 用途
------------- ------------------------------------------
!= 不等于号
<> 不等于号
:= 赋值号
=> 关系号
.. 范围运算符
|| 字符连接符
提示: ELSIF 不能写成 ELSEIF
简单循环
declare
x number;
begin
x:= 0;
loop
x:=x+1;
dbms_output.put_line(to_char(x));
exit when x=10;
end loop;
end;
DECLARE
V_counter BINARY_INTEGER := 1;
Begin
LOOP
Inert into temp_table
Values( v_counter, ‘loop index’ );
V_counter := v_counter + 1;
If v_counter > 50 then
Exit;
End if ;
End loop;
End;
• WHILE 循环
declare
x number;
begin
x:= 1;
while x<10 loop
dbms_output.put_line(to_char(x)||’还小于10’);
x:= x+1;
end loop;
end;
• 数字式循环
For 循环计数器 in 下限 .. 上限 .
begin
for I in 1 .. 10 loop
dbms_output.put_line('in=' || to_char(I));
end loop;
end;
为提高应用程序的健壮性,开发人员必须考虑程序可能出现的各种错误,并进行相应的处理。
Oracle中异常分为预定义例外,非预定义例外和自定义例外三种
预定义异常是指由PL/SQL所提供的系统异常.当PL/SQL应用程序违反了Oralce规则或系统限制时,则会隐含的触发一个内部异常。
PL/SQL为开发人员提供了二十多个预定义异常
DECLARE
CURSOR emp_cursor IS SELECT ename,sal FROM emp;
BEGIN
OPEN emp_cursor;
FOR emp_record IN emp_cursor LOOP
DBMS_OUTPUT.PUT_LINE(emp_record.ename);
END LOOP;
EXCEPTION
WHEN CURSOR_ALREADY_OPEN THEN
DBMS_OUTPUT.PUT_LINE('游标已经打开.');
END;
BEGIN
UPDATE DEPT SET DEPTNO = 20 WHERE DEPTNO = 10;
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
DBMS_OUTPUT.PUT_LINE(‘deptno列上不能出现重复值’);
END;
DECLARE
CURSOR emp_cursor IS SELECT ename,sal FROM emp;
emp_record emp_cursor%ROWTYPE;
BEGIN
FETCH emp_cursor INTO emp_record;
CLOSE emp_cursor;
EXCEPTION
WHEN INVALID_CURSOR THEN
DBMS_OUTPUT.PUT_LINE('请检查游标是否已经打开.');
END;
DECLARE
V_SAL EMP.SAL%TYPE;
BEGIN
SELECT SAL INTO V_SAL FROM EMP WHERE LOWER(ENAME) = LOWER('simth');
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('');
END;
DECLARE
TYPE emp_array_type IS VARRAY(20) OF VARCHAR2(10);
emp_array emp_array_type;
BEGIN
emp_array:=emp_array_type('SCOTT','MARY');
DBMS_OUTPUT.PUT_LINE(emp_array(3));
EXCEPTION
WHEN SUBSCRIPT_BEYOND_COUNT THEN
DBMS_OUTPUT.PUT_LINE('下标越界.');end;
自定义异常与Oracle错误没有任何关联,它是开发人员为特定情况所定义的异常.
自定义异常必须显式触发.使用步骤如下:
定义异常 -> 显式触发异常 -> 引用异常
首先要在定义部分(DECLARE)定义异常,然后在执行部分(BEGIN)触发异常(RAISE语句),
最后在异常处理部分(EXCEPTION)捕捉处理.
DECLARE
E_NO_EMPLOYEE EXCEPTION;
BEGIN
UPDATE EMP SET DEPTNO = 10 WHERE EMPNO = 7369;
IF SQL%NOTFOUND THEN
RAISE E_NO_EMPLOYEE;
END IF;
EXCEPTION
WHEN E_NO_EMPLOYEE THEN
DBMS_OUTPUT.PUT_LINE(‘该雇员不存在!’);
END;
CREATE OR REPLACE PROCEDURE raise_comm(eno NUMBER,commission NUMBER)
IS v_comm emp.comm%TYPE;
BEGIN
SELECT comm INTO v_comm FROM emp WHERE empno=eno;
IF v_comm IS NULL THEN
RAISE_APPLICATION_ERROR(-20001,'该员工无补助.');
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('该雇员不存在.');
END;
过程
用于执行动作的子程序。过程可以有多个入口及出口参数
CREATE OR REPLACE PROCEDURE 过程名 (入口参数1 [in|out|in out]类型,入口参数[in|out|in out] 类型) as
变量1 类型 ;变量2 类型 ;
begin
语句;
exception
when 例外 then语句; end ;
in –只读,不能修改out-只写,不能读值in out 读写
创建一个过程,指定人的工资加100
create or replace procedure Dp_add_gz(v_grid varchar2) as
n_rec number;
begin
select count(1) into n_rec from dual
where exists (select 1 from emp where empno = v_grid);
if n_rec > 0 then
update emp set sal = sal + 100 where empno = v_grid;
end if;
exception
when others then
null;
end;
函数必须有RETURN子句,并且有一个函数返回值,其他和PROCEDUCE一样。
CREATE OR REPLACE FUNCTION 函数名 (入口参数1类型,入口参数 类型) return type is
变量1 类型 ;变量2 类型 ;
Begin 语句; return ;
exception when 例外 then 语句; end ;
return 语句
一个函数可以有多个return 语句,但是只有一个可以被执行。当在函数执行的过程中,有return出现时,其后面的语句就不会在被执行了。
return 的类型必须和定义的类型相一致。只能通过out参数返回多个数值,语法和PROCEDUCE一样。省缺参数:同PRECEDUCE一样
发表评论
-
密码过期
2015-11-10 17:30 469oracle sql develop ,一个oracle客户 ... -
显式提交惹的祸
2015-04-19 10:28 518需要开发一个指标监控系统,数据库是oracle的 之 ... -
oracle性能优化31条建议
2014-05-07 22:32 5151.ORACLE的优化器共有3种 A、RULE ... -
oracle 优化设计
2014-03-13 16:17 703本文主要从大型数据库ORACLE环境四个不同级别的调整分析入手 ... -
oracle scn recovery data
2014-03-13 16:08 508今天测试下了oracle在删除表的数据后的恢复方法。 在or ... -
事务级别
2014-02-21 22:03 5261.事务定义 事务是保持数据的一致性,它 ... -
视图详细
2014-02-21 21:07 525Oracle的数据库对象分为五种:表,视图,序列,索引和同义词 ... -
mins
2014-02-15 14:34 439create table test1 ( name var ... -
rownum
2014-02-14 22:48 538存在表T(a,b,c,d),要根据字段c排序后取第21—30条 ... -
having
2014-02-13 21:28 4801.如何只显示重复数据,或不显示重复数据 显示重复:se ... -
insert select update delete
2013-08-20 21:49 1198SQL四条最基本的数据操作语句 insert select u ... -
存储过程
2013-07-17 20:39 4661.基本结构 CREATE OR REPLACEPROCE ... -
存储过程
2013-07-17 20:36 5531、什么是存储过程。 ... -
数据导出导入
2013-07-11 21:14 408电脑内存是4个G的,处理器也是目前比较流行的i3,所以很有理 ...
相关推荐
利用SQL游标存储过程分页方案,以前用过,应该还行
游标和存储过程是数据库管理系统中的重要概念,主要用于处理复杂的查询和事务操作。游标允许用户在结果集中逐行处理数据,而存储过程则是一组预编译的SQL语句集合,可以用来执行一系列数据库操作。 游标在数据库中...
本篇文章将深入探讨SQL Server中游标的使用,以及如何在存储过程中集成游标。 首先,我们需要了解游标的几个基本概念: 1. 游标的类型:包括静态、动态、键集和只进。静态游标在打开时加载所有数据,数据更改不会...
根据提供的文件信息,本文将详细解释一个MySQL存储过程的例子,其中包含了游标的使用。这个存储过程主要用于处理一批数据,涉及到日期范围内的数据处理、异常处理等。下面将逐一解析存储过程中涉及的重要知识点。 #...
数据库编程技术——游标、存储过程与触发器 数据库编程技术是数据库管理系统中的一种重要技术,用于实现数据库的自动化管理和数据处理。本节实验重点介绍游标、存储过程和触发器三种数据库编程技术的应用。 一、...
本文将深入探讨SQL存储过程中的常用函数、游标用法以及日期函数。 一、字符函数 字符函数主要用于对字符串进行各种操作。例如: 1. `LEN(str)`:返回字符串`str`的长度。 2. `SUBSTRING(str, start, length)`:从...
Mysql存储过程游标触发器
本题涉及的知识点集中在使用SQL中的游标(Cursor)来实现一个存储过程,该过程用于处理学生成绩表的数据,特别是检查并填充学分字段。 首先,我们要理解存储过程的作用。存储过程允许我们将多次使用的SQL逻辑封装在...
SQL存储过程和游标的运用 SQL存储过程和游标是SQL语言中两个非常重要的概念,它们可以帮助开发者更好地管理和处理数据。在本节中,我们将详细介绍存储过程和游标的基本概念和应用。 什么是存储过程 存储过程是一...
PLSQL,全称为Procedural Language/Structured Query Language,是Oracle数据库系统中用于编写存储过程、函数、包等数据库程序的编程语言。本压缩包集合了关于PLSQL的各种关键知识点,包括语法、异常处理、指针和...
在Oracle数据库中,游标(Cursor)是一种非常重要的概念,特别是在编写存储过程和函数时。游标允许我们处理单行或多行数据集,一次处理一行,这样可以进行精细化的数据操作。在本篇讨论中,我们将深入理解Oracle游标...
### 游标与存储过程在SQL Server中的应用 #### 一、游标的使用方法 游标是数据库管理系统中用于处理查询结果集的一种机制,它允许用户逐行地访问查询结果,而不是一次返回所有数据。这对于大数据量处理尤其有用,...
游标和存储过程是数据库管理中非常重要的两个概念,它们在数据处理和应用程序开发中扮演着关键角色。本文将详细探讨这两个概念,以及如何在程序中创建和调用它们。 首先,我们来看“游标”(Cursor)。游标提供了一...
Oracle存储过程中的“Out”游标是数据库编程中一种常用的技术,主要用于在PL/SQL块中返回结果集到调用者。在这个场景中,我们有三个文件:TESTPACKAGE.txt,CURSOR_TEST2.txt和OracleProcedure.java,分别涉及Oracle...
本文将深入探讨存储过程、触发器和游标,以及它们在实际应用中的综合使用。 首先,让我们来理解存储过程。存储过程是预编译的SQL语句集合,它封装了一系列数据库操作并在需要时执行。这种高级的SQL构造可以提高性能...
本实例将深入探讨如何构建一个完整的图书管理系统,涉及的关键知识点包括数据库的概念和逻辑结构设计,以及游标和存储过程的使用。 一、数据库概念与逻辑结构设计 1. 数据库概念:数据库是一个组织和存储数据的系统...
Oracle 存储过程调用 CallabledStatement 实用例子(IN OUT 传游标) 一、Oracle 存储过程简介 Oracle 存储过程是一种可以在 Oracle 数据库中存储和执行的程序单元。存储过程可以由多种语言编写,例如 PL/SQL、...
### 存储过程和游标知识点详解 #### 一、存储过程的概念与作用 存储过程是一种在数据库中存储并编译好的SQL程序,它可以接受参数并返回结果集或执行特定的任务。存储过程的主要优势在于提高了代码重用性、减少了...
"Oracle存储过程游标详解" Oracle 存储过程游标是指在 Oracle 数据库中使用游标来实现对结果集的处理和操作。游标可以分为静态游标和REF游标两种类型。静态游标是指结果集已经确实(静态定义)的游标,可以进一步...