`
zengshaotao
  • 浏览: 792893 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

游标,存储过程

 
阅读更多
PL/SQL程序有以下优点:
软件生产效率很高;系统性能良好;系统资源利用率高(如:节省内存)
Sql基本的语法结构
Declare 
    /*   声明部分: 在此  声明PL/SQL用到的变量,类型及光标 */
begin
    /*  执行部分:  过程及SQL 语句  , 即程序的主要部分  */
Exception
   /* 执行异常部分: 错误处理  */
End;
定义部分:    定义将在执行部分调用的所有变量,常量,游标,和用户自定义的异常处理. 这部分可以没有.
执行部分:    包括对数据库进行操作的SQL语句,以及对语句进行组织,控制的PL/SQL语句。这部分在PL/SQL块中必须存在.   
例外处理部分:可执行部分中的语句,在执行过程中出错或出现非正常现象时,所应做的相应处理. 这部分可以没有
第一次使用的变量必须在定义部分定义,只有定义过的变量才能在执行部分引用.需要注意的是块可以嵌套使用.
变量类型
类型         子类            说 明            范围       ORACLE限制
--------------------   ------------    ------------   ------------------------
Char      character       定长字符串         032767      255
            Rowid    
Varchar2    varchar        可变字符串        032767      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          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游标存储过程分页方案

    利用SQL游标存储过程分页方案,以前用过,应该还行

    游标 存储过程游标 存储过程.doc

    游标和存储过程是数据库管理系统中的重要概念,主要用于处理复杂的查询和事务操作。游标允许用户在结果集中逐行处理数据,而存储过程则是一组预编译的SQL语句集合,可以用来执行一系列数据库操作。 游标在数据库中...

    sqlserver游标存储过程的使用

    本篇文章将深入探讨SQL Server中游标的使用,以及如何在存储过程中集成游标。 首先,我们需要了解游标的几个基本概念: 1. 游标的类型:包括静态、动态、键集和只进。静态游标在打开时加载所有数据,数据更改不会...

    mysql游标存储过程例子

    根据提供的文件信息,本文将详细解释一个MySQL存储过程的例子,其中包含了游标的使用。这个存储过程主要用于处理一批数据,涉及到日期范围内的数据处理、异常处理等。下面将逐一解析存储过程中涉及的重要知识点。 #...

    实验八数据库编程技术——游标、存储过程与触发器.pdf

    数据库编程技术——游标、存储过程与触发器 数据库编程技术是数据库管理系统中的一种重要技术,用于实现数据库的自动化管理和数据处理。本节实验重点介绍游标、存储过程和触发器三种数据库编程技术的应用。 一、...

    sql 存储过程常用函数及游标用法

    本文将深入探讨SQL存储过程中的常用函数、游标用法以及日期函数。 一、字符函数 字符函数主要用于对字符串进行各种操作。例如: 1. `LEN(str)`:返回字符串`str`的长度。 2. `SUBSTRING(str, start, length)`:从...

    Mysql存储过程游标触发器

    Mysql存储过程游标触发器

    SQL 带游标的存储过程

    本题涉及的知识点集中在使用SQL中的游标(Cursor)来实现一个存储过程,该过程用于处理学生成绩表的数据,特别是检查并填充学分字段。 首先,我们要理解存储过程的作用。存储过程允许我们将多次使用的SQL逻辑封装在...

    sql存储过程和游标的运用

    SQL存储过程和游标的运用 SQL存储过程和游标是SQL语言中两个非常重要的概念,它们可以帮助开发者更好地管理和处理数据。在本节中,我们将详细介绍存储过程和游标的基本概念和应用。 什么是存储过程 存储过程是一...

    PLSQL 文档集合包(语法 异常 指针 游标 存储过程...)

    PLSQL,全称为Procedural Language/Structured Query Language,是Oracle数据库系统中用于编写存储过程、函数、包等数据库程序的编程语言。本压缩包集合了关于PLSQL的各种关键知识点,包括语法、异常处理、指针和...

    ORACLE 游标 异常 存储过程

    在Oracle数据库中,游标(Cursor)是一种非常重要的概念,特别是在编写存储过程和函数时。游标允许我们处理单行或多行数据集,一次处理一行,这样可以进行精细化的数据操作。在本篇讨论中,我们将深入理解Oracle游标...

    游标、存储过程的使用事例

    ### 游标与存储过程在SQL Server中的应用 #### 一、游标的使用方法 游标是数据库管理系统中用于处理查询结果集的一种机制,它允许用户逐行地访问查询结果,而不是一次返回所有数据。这对于大数据量处理尤其有用,...

    游标 和 存储过程的创建 及 在程序中的调用

    游标和存储过程是数据库管理中非常重要的两个概念,它们在数据处理和应用程序开发中扮演着关键角色。本文将详细探讨这两个概念,以及如何在程序中创建和调用它们。 首先,我们来看“游标”(Cursor)。游标提供了一...

    Oracle存储过程out游标

    Oracle存储过程中的“Out”游标是数据库编程中一种常用的技术,主要用于在PL/SQL块中返回结果集到调用者。在这个场景中,我们有三个文件:TESTPACKAGE.txt,CURSOR_TEST2.txt和OracleProcedure.java,分别涉及Oracle...

    存储过程触发器 游标

    本文将深入探讨存储过程、触发器和游标,以及它们在实际应用中的综合使用。 首先,让我们来理解存储过程。存储过程是预编译的SQL语句集合,它封装了一系列数据库操作并在需要时执行。这种高级的SQL构造可以提高性能...

    数据库实例详解——图书管理系统(包括SQL代码,游标,存储过程)

    本实例将深入探讨如何构建一个完整的图书管理系统,涉及的关键知识点包括数据库的概念和逻辑结构设计,以及游标和存储过程的使用。 一、数据库概念与逻辑结构设计 1. 数据库概念:数据库是一个组织和存储数据的系统...

    用callabledStatement调用oracle存储过程实用例子(IN OUT 传游标)

    Oracle 存储过程调用 CallabledStatement 实用例子(IN OUT 传游标) 一、Oracle 存储过程简介 Oracle 存储过程是一种可以在 Oracle 数据库中存储和执行的程序单元。存储过程可以由多种语言编写,例如 PL/SQL、...

    存储过程和游标

    ### 存储过程和游标知识点详解 #### 一、存储过程的概念与作用 存储过程是一种在数据库中存储并编译好的SQL程序,它可以接受参数并返回结果集或执行特定的任务。存储过程的主要优势在于提高了代码重用性、减少了...

    Oracle存储过程游标详解

    "Oracle存储过程游标详解" Oracle 存储过程游标是指在 Oracle 数据库中使用游标来实现对结果集的处理和操作。游标可以分为静态游标和REF游标两种类型。静态游标是指结果集已经确实(静态定义)的游标,可以进一步...

Global site tag (gtag.js) - Google Analytics