转自:http://blog.chinaunix.net/uid-20495387-id-174394.html

http://www.cnblogs.com/rootq/articles/1100086.html

http://blog.sina.com.cn/s/blog_7540bf5f0100q82e.html

1.基本结构

  1. CREATE OR REPLACE PROCEDURE 存储过程名字
  2. (
  3. 参数1 IN NUMBER,
  4. 参数2 IN NUMBER,
  5. 参数3 OUT NUMBER
  6. ) IS
  7. 变量1 INTEGER := 默认值;
  8. 变量2 DATE;
  9. BEGIN

  10. EXCEPTION
  11. WHEN 异常类别 THEN

  12. WHEN OTHERS THEN

  13. END 存储过程名字;

2.基本操作

  • 变量赋值 V_TEST := 1;

    动态赋值 SELECT COL1,COL2,… INTO VAR1,VAR2,… FROM … WHERE …;

    字符相加  ‘STRING1′ || ‘STRING2′;

    相等判断 =而不是==;

    逻辑判断 AND,OR,>,<,<>;

    打印输出 dbms_output.put_line();

    是否为空 V_TEST IS (NOT) NULL;

    提交回滚 COMMIT/ROLLBACK;

    异常捕捉 BEGIN … EXCEPTION WHEN … THEN … END;

3.IF 判断

  1. IF (判断条件) THEN
  2. BEGIN

  3. END;
  4. ELSIF THEN

  5. ELSE

  6. END IF;

4.WHILE 循环

  1. WHILE (判断条件) LOOP
  2. BEGIN

  3. END;
  4. END LOOP;

5.FOR 循环

  1. FOR X IN (SELECT col1,col2 …) LOOP
  2. BEGIN
  3. 引用X.col1X.col2

  4. END;
  5. END LOOP;

6.常见FUNCTION

常用函数的普通用法:

  1. SYSDATE:用来得到系统的当前日期;
  2. TO_NUMBER(STR):将字符串转换成数字;若转换不成功,则抛错:invalid number;
  3. TO_CHAR(?):?可支持很多的类型,比如NUM,DATE……;DATE用得比较多,一般来说有如下用法:TO_CHAR(SYSDATE, ‘YYYY-MM-DD HH24:MI:SS’):将当前日期按照格式输出完整字符串;其中的日期格式可以自行定义;
  4. TO_DATE(STR,FORMAT):对字符串按照一定格式解析成Date型;
  5. NVL(col,defaultValue):对col判断是否为NULL,若为NULL,则返回defaultValue;
  6. CONCAT(STR1,STR2):连接两个字符串,功能与||相同;
  7. LENGTH(STR):返回字符串的长度,其中中文字符的长度计算要视DB的编码而定,在GBK编码下,中文也算1个字符;若需要中文字符长度算2个字符,则可以用LENGTHB(STR)代替;简单来说,LENGTH返回字符长度;LENGTHB返回字节长度;
  8. SUBSTR(str,start,count):截取子字符串,从start开始,取count个;start为0和1的效果是一样的,都是从str的第一个字符开始截取;若start>=LENGTH(str),直接返回空,不会抛错;
  9. INSTR(STR1,STR2,I,J):在一个字符串中搜索指定的字符,返回发现指定的字符的位置;

    STR1:被搜索的字符串

    STR2:希望搜索的字符串

    I:搜索的开始位置,默认为1

    J:第几次出现的位置,默认为1

  10. LOWER/UPPER(STR):将字符串全部转成小写或者大写;

    在GBK编码下,该函数对中文无效;
  11. LTRIM/RTRIM(STR):删除左边货右边出现的空格字符串;
  12. FLOOR(NUMBER):对给定的数字取整数;
  13. MOD(num1,num2):返回num1除以num2的余数;

    num1和num2可以带有小数位;

    返回的值也可能有小数位;

  14. ROUND(num):对num四舍五入取值;
  15. TRUNC(num):对num截取整数,去掉小数位,不进行四舍五入;

    功能与FLOOR类似;当然也可以在参数中指定精度;
  16. TRUNC(Date):对date截取到天,去掉小时分钟之类的,其返回类型仍然为Date;

    类似的,也可以在参数中指定Date截取级别,比如’hh’;
  17. ADD_MONTHS(Date,num):对Date加上num个月,num可以为负数,表示减去几个月;

    num可以有小数位,但是并不会起效,效果相当于ADD_MONTHS(Date,TRUNC(num));
  18. CHARTOROWID/ROWIDTOCHAR:将字符数据类型转换为ROWID类型或者相反;
  19. AVG/MIN/MAX/SUM/COUNT(DISTINCT|ALL col):对某字段取平均、最小、最大、求和、计数;默认为ALL,若需要对不重复值运算,则用DISTINCT参数;
    1. CASE WHEN THEN
    2. WHEN THEN
    3. ELSE
    4. END:根据不同条件取不同的值,与JAVA中的CASE也很类似;

7.CURSOR 游标

无参数申明:

  1. CURSOR CUR_NAME IS SELECT COL1,COL2,… FROM WHERE …;

带参数申明:

  1. CURSOR CUR_NAME(PARAM1 DATA_TYPE,PARAM2 DATA_TYPE,…) IS SELECT COL1,COL2,… FROM WHERE …;

在大多数时候我们在设计程序的时候都遵循下面的步骤:

  1. 打开游标 open cs1;
  2. 开始循环 while cs1%found loop | for column_name in .. LOOP
  3. 从游标中取值 fetch .. into.. |
  4. 检查那一行被返回
  5. 处理
  6. 关闭循环 end loop;
  7. 关闭游标 if cs1&isopen then close cs1;

游标属性:

  • %FOUND:变量最后从游标中获取记录的时候,在结果集中找到了记录。

    %NOTFOUND:变量最后从游标中获取记录的时候,在结果集中没有找到记录。

    %ROWCOUNT:当前时刻已经从游标中获取的记录数量。

    %ISOPEN:是否打开。

静态游标:

  • 分为显式游标和隐式游标。

REF游标:

  • 是一种引用类型,类似于指针。

显式和隐式游标的区别:

  • 尽量使用隐式游标,避免编写附加的游标控制代码(声明,打开,获取,关闭),也不需要声明变量来保存从游标中获取的数据。

REF CURSOR游标:

  • 动态游标,在运行的时候才能确定游标使用的查询。分类:

    强类型(限制)REF CURSOR,规定返回类型

    弱类型(非限制)REF CURSOR,不规定返回类型,可以获取任何结果集。

8.用FOR IN使用CURSOR

  1. FOR CUR_RS IN CUR_NAME LOOP
  2. BEGIN
  3. 引用CUR_RS.COL1,CUR_RS.COL2,…

  4. END;
  5. END LOOP;

9.用FETCH INTO使用CURSOR

  1. LOOP
  2. FETCH CUR_NAME INTO V_COL1,V_COL2,…;

  3. EXIT WHEN CUR_NAME%NOTFOUND;
  4. END LOOP;

10.用BULK COLLECT使用CURSOR,用于批量操作,提高效率

–申明TABLE数据类别

  1. TYPE TYPE_NAME IS TABLE OF DATA_TYPE;
  2. eg TYPE T_ROWID IS TABLE OF UROWID;

–申明变量

  1. VAR_NAME TYPE_NAME;
  2. egVAR_ROWID T_ROWID;

–LOOP 1000条一个批次

  1. FETCH CUR_NAME BULK COLLECT INTO VAR_ROWID,V_COL2,… LIMIT 1000;
  2. FORALL i IN VAR_ROWID.FIRST .. VAR_ROWID.LAST
  3. ONE SQL;
  4. COMMIT;
  5. EXIT WHEN CUR_NAME%NOTFOUND;
  6. END LOOP;

11.EXIT WHEN CUR_NAME%NOTFOUND 位置

在配合FETCH INTO语句使用时,EXIT WHEN CUR_NAME%NOTFOUND可以放在循环的开始处,也可以放在最后面;视具体场景而定;

WHEN CUR_NAME%NOTFOUND也可以用其他的判断条件替换;

比如在用BULK COLLECT时,就可以用EXIT WHEN VAR_ROWID.COUNT = 0;不过此时需要放在FETCH之后FORALL之前;

12. 其他使用注意事项

1.SELECT INTO语句要求SELECT出来的RESULT至少有一条记录;

若RS为NULL,则会抛出NO_DATA_FOUND的EXCEPTION;所以需要进行异常捕获;

2.进行UPDATE、DELETE操作时可以用ROWID替换PK可以提高执行效率;

因为ROWID是直接定位到物理磁盘地址,而无需先从PK Index中查询,从而有效降低IO次数;

比如UPDATE MD_USER SET NAME = XX WHERE ROWID = ?;

不过用ROWID时需要小心,因为1)ROWID会被重用;2)在有GROUP BY语句的条件中无法使用;

3.EXCEPTION捕获之后若不需要做任何事情,则可以如下处理:

BEGIN … EXCEPTION WHEN NO_DATA_FOUND THEN NULL; END;

4.EXCEPTION能够捕获的常见类别有:

NO_DATA_FOUND:代码块中某条SELECT INTO语句返回的RS为NULL;

TOO_MANG_ROWS:SELECT INTO语句符合条件的记录有多条返回;

DUP_VAL_ON_INDEX:对于数据库表中的某一列,该列已经被限制为唯一索引,程序试图存储两个重复的值;

VALUE_ERROR:在转换字符类型,截取或长度受限时,会发生该异常,如一个字符分配给一个变量,而该变量声明的长度比该字符短,就会引发该异常;

STORAGE_ERROR:内存溢出;

ZERO_DIVIDE:除数为零;

CASE_NOT_FOUND:对于选择case语句,没有与之相匹配的条件,同时,也没有else语句捕获其他的条件;

CURSOR_ALREADY_OPEN:程序试图打开一个已经打开的游标;

TIMEOUT_ON_RESOURCE:系统在等待某一资源,时间超时;

OTHERS:所有;

除此之外,还可以用RAISE来抛出一个自定义的EXCEPTION;比如

DECLARE MY_ERROR EXCEPTION;

BEGIN

IF (…) THEN

RAISE MY_ERROR;

END IF;

EXCEPTION WHEN MY_ERROR THEN

WHEN OTHERS THEN

END;

5.批量操作BULK COLLECT INTO情况下,FORALL下面只能有一条SQL操作,也不能是存过调用;若需要执行多条SQL,则需要用多个FORALL,比如

LOOP

–1000条一个批次

FETCH CUR_NAME BULK COLLECT INTO VAR_ROWID,V_COL2,… LIMIT 1000;

FORALL i IN VAR_ROWID.FIRST .. VAR_ROWID.LAST

INSERT INTO …;

FORALL i IN VAR_ROWID.FIRST .. VAR_ROWID.LAST

UPDATE TABLE_NAME SET …;

COMMIT;

EXIT WHEN CUR_NAME%NOTFOUND;

END LOOP;

6.重复数据高效清理SQL:

DELETE FROM TABLE_NAME tn

WHERE tn.ROWID >

(SELECT MIN(x.ROWID)

FROM TABLE_NAME x

WHERE x.col1 = tn.col1

AND x.col2 = tn.col2);

–根据col1、col2两个字段清理,清理后两个字段满足unique约束;

7.一条SQL搞定如下场景:当数据存在进行更新,否则进行新增;

MERGE INTO TABLE_NAME tn

USING (SELECT v_pk AS pk FROM DUAL) tmps

ON (tn.pk = tmps.pk)

WHEN MATCHED THEN

UPDATE

SET col1 = ?, col2 = ? ,…

WHEN NOT MATCHED THEN

INSERT (col1, col2, …)

VALUES (v_col1, v_col2, …);

注意:ON子句中的字段不能在UPDATE子句中进行SET操作;

8.CONNECT BY语句使用

SQL> SELECT rownum rn FROM dual CONNECT BY rownum <= 5;

RN

———-

1

2

3

4

5

该语句一般配合笛卡尔积使用,一条语句搞定很多条INSERT语句的事情,可以大大减少SQL代码量;

 

13. 用java调用oracle存储过程

–一般过程:

  1. //1、call+包名+存储过程名(传入、传出值用?)
  2. String str="{call SMSBUSINESS.deleteZhZMember(?,?,?)}";
  3. //2、建立连接
  4. Connection conn=null;
  5. conn=DriverManager.getConnection();
  6. //3、使用java.sql.*类
  7. CallableStatement cs=conn.prepareCall(str);
  8. //4、传入in值
  9. cs.setInt(1,id);
  10. cs.setInt(2,-2);
  11. //5、设置out值
  12. cs.registerOutParameter(3,Types.NUMERIC);
  13. //6、执行
  14. cs.excuse();
  15. //7、取出out值
  16. int flag=cs.getInt(3);
  17. //8、关连接
  18. conn.close();

–无返回值的存储过程

存储过程为:

  1. CREATE OR REPLACE PROCEDURE TESTA(PARA1 IN VARCHAR2,PARA2 IN VARCHAR2) AS
  2. BEGIN
  3. INSERT INTO HYQ.B_ID (I_ID,I_NAME) VALUES (PARA1, PARA2);
  4. END TESTA;

Java调用如下:

  1. import java.sql.CallableStatement;
  2. import java.sql.Connection;
  3. import java.sql.DriverManager;
  4. import java.sql.ResultSet;
  5. import java.sql.SQLException;
  6. import java.sql.Statement;
  7.  
  8. /**
  9. * @ClassName:
  10. * @Description: TODO
  11. * @author:
  12. * @Date: 2015-05-12 16:33:53
  13. */
  14.  
  15. public class TestProcedureOne {
  16.  
  17. public static void main(String[] args) {
  18. String driver = "oracle.jdbc.driver.OracleDriver";
  19. String strUrl = "jdbc:oracle:thin:@127.0.0.1:1521: hyq ";
  20. Statement stmt = null;
  21. ResultSet rs = null;
  22. Connection conn = null;
  23.  
  24. try {
  25. Class.forName(driver);
  26. conn = DriverManager.getConnection(strUrl, " hyq ", " hyq ");
  27. CallableStatement proc = null; // 创建执行存储过程的对象
  28. proc = conn.prepareCall("{ call HYQ.TESTA(?,?) }"); // 设置存储过程
  29. // call为关键字.
  30. proc.setString(1, "100"); // 设置第一个输入参数
  31. proc.setString(2, "TestOne");// 设置第二个输入参数
  32. proc.execute();// 执行
  33. } catch (SQLException ex2) {
  34. ex2.printStackTrace();
  35. } catch (Exception ex2) {
  36. ex2.printStackTrace();
  37. } finally {
  38. try {
  39. if (rs != null) {
  40. rs.close();
  41. if (stmt != null) {
  42. stmt.close();
  43. }
  44. if (conn != null) {
  45. conn.close();
  46. }
  47. }
  48. } catch (SQLException ex1) {
  49. }
  50. }
  51. }
  52. }

–有返回值的存储过程

存储过程为:

  1. CREATE OR REPLACE PROCEDURE TESTB(PARA1 IN VARCHAR2,PARA2 OUT VARCHAR2) AS
  2. BEGIN
  3. SELECT INTO PARA2 FROM TESTTB WHERE I_ID= PARA1;
  4. END TESTB;

Java调用如下:

  1. import java.sql.CallableStatement;
  2. import java.sql.Connection;
  3. import java.sql.DriverManager;
  4. import java.sql.ResultSet;
  5. import java.sql.SQLException;
  6. import java.sql.Statement;
  7. import java.sql.Types;
  8.  
  9. /**
  10. * @ClassName:
  11. * @Description: TODO
  12. * @author:
  13. * @Date: 2015-05-12 16:33:53
  14. */
  15.  
  16. public class TestProcedureTWO {
  17. public TestProcedureTWO() {
  18. }
  19. public static void main(String[] args ){
  20. String driver = "oracle.jdbc.driver.OracleDriver";
  21. String strUrl = "jdbc:oracle:thin:@127.0.0.1:1521:hyq";
  22. Statement stmt = null;
  23. ResultSet rs = null;
  24. Connection conn = null;
  25. try {
  26. Class.forName(driver);
  27. conn = DriverManager.getConnection(strUrl, " hyq ", " hyq ");
  28. CallableStatement proc = null;
  29. proc = conn.prepareCall("{ call HYQ.TESTB(?,?) }"); //设置存储过程
  30. proc.setString(1, "100");//设置第一个参数输入参数
  31. proc.registerOutParameter(2, Types.VARCHAR);//第二个参数输出参数,是VARCHAR类型的
  32. proc.execute();//执行
  33. String testPrint = proc.getString(2);//获得输出参数
  34. System.out.println("=testPrint=is="+testPrint);
  35. }
  36. catch (SQLException ex2) {
  37. ex2.printStackTrace();
  38. }
  39. catch (Exception ex2) {
  40. ex2.printStackTrace();
  41. }
  42. finally{
  43. try {
  44. if(rs != null){
  45. rs.close();
  46. if(stmt!=null){
  47. stmt.close();
  48. }
  49. if(conn!=null){
  50. conn.close();
  51. }
  52. }
  53. }
  54. catch (SQLException ex1) {
  55. }
  56. }
  57. }
  58. }

Oracle 存储过程学习的更多相关文章

  1. Oracle存储过程学习使用

    存储过程创建语法: create or replace procedure 存储过程名(param1 in type,param2 out type) as 变量1 类型(值范围); 变量2 类型(值 ...

  2. ORACLE存储过程学习

    存储过程 1 CREATE OR REPLACE PROCEDURE 存储过程名 2 IS 3 BEGIN 4 NULL; 5 END; 行1: CREATE OR REPLACE PROCEDURE ...

  3. Oracle存储过程学习备忘

    之前的项目使用存储过程很少,但在实际的项目中,存储过程的使用是必不可少的. 存储过程是一组为了完成特定功能的SQL 语句 集,经编译后存储在数据库中:存储过程创建后,一次编译在程序中可以多次调用,对安 ...

  4. Oracle 存储过程学习笔记

    1.存储过程简单实例 CREATE OR REPLACE PROCEDURE 存储过程名称 (参数in,参数out) AS -- 变量声明,每个声明用分号结束.可以在声明的同时初始化 name ); ...

  5. Oracle存储过程学习笔记

    SQL是一种语言! SQL是一种语言! SQL是一种语言! 个人理解:存储过程就相当于Java中的方法;声明变量区域就相当于java中的声明局部变量一样,只是放到一个指定区域定义了 一.先看一部分基础 ...

  6. oracle 存储过程学习感悟

    1.跟大白话差不多 2.if...then.... else ....写的比较多 3.调用存储过程命令:execute procedure_name 4.调用存储函数命令:select '0' str ...

  7. oracle存储过程学习---包的概念

    转自:http://www.iteye.com/topic/1111793 一.包的概念   类似于一个容器,能打包相应的Pl/SQL变量.常量.函数.过程.复合数据类型等元素到这个容器内.用来限制  ...

  8. 用java调用oracle存储过程总结(转)

    //1.call+包名+存储过程名(传入.传出值用?) String str="{call SMSBUSINESS.deleteZhZMember(?,?,?)}"; //2.建立 ...

  9. oracle 存储过程 动态sql语句

    一.在oracle项目开发中越到问题: 在利用ODP向oracle中插入数据时,如果这样写:   insert into clobTable (id, story) values(1,'....'); ...

随机推荐

  1. Java——Cookie与Session

    Cookie通过客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份. 1.Cookie  1.1概念及使用方法 Cookie实际上是一小段文本信息.客户端请求服务器,如果服务 ...

  2. Cocoapods的安装报错 - Error installing pods:activesupport requires Ruby version >=2.2.2

    1.打开终端 2 移除现有 Ruby 默认源 输入以下指令 $gem sources --remove https://rubygems.org/ 3.使用新的源 输入以下指令 $gem source ...

  3. Android Programming: Pushing the Limits -- Chapter 6: Services and Background Tasks

    什么时候使用Service 服务类型 开启服务 后台运行 服务通信 附加资源 什么时候使用Service: @.任何与用户界面无关的操作,可移到后台线程,然后由一个Service来控制这个线程. 服务 ...

  4. SQL学习笔记----更改SQL默认的端口号

    1.SQLServer配置管理器----SQLServer网络配置----MSSQLSERVER的协议---TCP/IP(已启用)---IP地址 清空素有的IP,在IPALL下更改默认的端口: 2. ...

  5. JavaWeb学习之Path总结、ServletContext、ServletResponse、ServletRequest(3)

    1.Path总结 1.java项目 1 File file = new File(""); file.getAbsolutePath(); * 使用java命令,输出路径是,当前j ...

  6. 全局压缩http响应头

    见代码: public class CompressAttribute : ActionFilterAttribute { public override void OnActionExecuting ...

  7. android 入门-工序

    页面: 1.启动页 2.引导页 3.主页面 自定义控件: 轮播控件 轮播列表控件 弹出控件 加载控件 引导页控件 下拉刷新 上拉加载控件

  8. android 入门-安装环境

    1.安装jdk 相关链接 2.安装adt 里面包含eclipse 3.下载androidsdk 4.打开eclipse 找到windows -> 属性 -> android 主目录 复制 ...

  9. hdu 5000 dp **

    题目中提到  It guarantees that the sum of T[i] in each test case is no more than 2000 and 1 <= T[i]. 加 ...

  10. hdu 4762 公式 java

    n/(n)^(m-1) import java.io.*; import java.math.*; import java.util.*; public class Main { static Big ...