设为首页 收藏本站
查看: 3218|回复: 0

[经验分享] JDBC调用Oracle的存储过程

[复制链接]

尚未签到

发表于 2016-7-29 02:21:24 | 显示全部楼层 |阅读模式
  本文主要是总结 如何实现 JDBC调用Oracle的存储过程,从以下情况分别介绍:

  • [1]、只有输入IN参数,没有输出OUT参数
  • [2]、既有输入IN参数,也有输出OUT参数,输出是简单值(非列表)
  • [3]、既有输入IN参数,也有输出OUT参数,输出是列表
  • [4]、输入输出参数是同一个(IN OUT)
【准备工作】
  创建一个测试表TMP_MICHAEL ,并插入数据,SQL如下:
Sql代码   DSC0000.png


  • create table TMP_MICHAEL  
  • (  
  •   USER_ID    VARCHAR2(20),  
  •   USER_NAME  VARCHAR2(10),  
  •   SALARY     NUMBER(8,2),  
  •   OTHER_INFO VARCHAR2(100)  
  • )  
  •   
  • insert into TMP_MICHAEL (USER_ID, USER_NAME, SALARY, OTHER_INFO)  
  • values ('michael''Michael', 5000, 'http://sjsky.iyunv.com');  
  • insert into TMP_MICHAEL (USER_ID, USER_NAME, SALARY, OTHER_INFO)  
  • values ('zhangsan''张三', 10000, null);  
  • insert into TMP_MICHAEL (USER_ID, USER_NAME, SALARY, OTHER_INFO)  
  • values ('aoi_sola''苍井空', 99999.99, 'twitter account');  
  • insert into TMP_MICHAEL (USER_ID, USER_NAME, SALARY, OTHER_INFO)  
  • values ('李四''李四', 2500, null);  

  Oracle jdbc 常量:
Java代码  


  • private final static String DB_DRIVER = "oracle.jdbc.driver.OracleDriver";  
  • private final static String DB_CONNECTION = "jdbc:oracle:thin:@127.0.0.1:1521:Ora11g";  
  • private final static String DB_NAME = "mytest";  
  • private final static String DB_PWd = "111111";  

 [一]、只有输入IN参数,没有输出OUT参数
 
 
存储过程 TEST_MICHAEL_NOOUT 的相关SQL:
Sql代码  


  • CREATE OR REPLACE PROCEDURE TEST_MICHAEL_NOOUT(P_USERID    IN VARCHAR2,  
  •                                                P_USERNAME  IN VARCHAR2,  
  •                                                P_SALARY    IN NUMBER,  
  •                                                P_OTHERINFO IN VARCHAR2) IS  
  • BEGIN  
  •   
  •   INSERT INTO TMP_MICHAEL  
  •     (USER_ID, USER_NAME, SALARY, OTHER_INFO)  
  •   VALUES  
  •     (P_USERID, P_USERNAME, P_SALARY, P_OTHERINFO);  
  •   
  • END TEST_MICHAEL_NOOUT;  

调用代码如下:
Java代码  


  • /** 
  •     * 测试调用存储过程:无返回值 
  •     * @blog http://sjsky.iyunv.com 
  •     * @author Michael 
  •     * @throws Exception 
  •     */  
  •    public static void testProcNoOut() throws Exception {  
  •        System.out.println("-------  start 测试调用存储过程:无返回值");  
  •        Connection conn = null;  
  •        CallableStatement callStmt = null;  
  •        try {  
  •            Class.forName(DB_DRIVER);  
  •            conn = DriverManager.getConnection(DB_CONNECTION, DB_NAME, DB_PWd);  
  •            // 存储过程 TEST_MICHAEL_NOOUT 其实是向数据库插入一条数据  
  •            callStmt = conn.prepareCall("{call TEST_MICHAEL_NOOUT(?,?,?,?)}");  
  •   
  •            // 参数index从1开始,依次 1,2,3...  
  •            callStmt.setString(1"jdbc");  
  •            callStmt.setString(2"JDBC");  
  •            callStmt.setDouble(38000.00);  
  •            callStmt.setString(4"http://sjsky.iyunv.com");  
  •            callStmt.execute();  
  •            System.out.println("-------  Test End.");  
  •        } catch (Exception e) {  
  •            e.printStackTrace(System.out);  
  •        } finally {  
  •            if (null != callStmt) {  
  •                callStmt.close();  
  •            }  
  •            if (null != conn) {  
  •                conn.close();  
  •            }  
  •        }  
  •    }  

 运行后查询数据库内容,已经成功插入数据,截图如下:

DSC0001.png
 
[二]、既有输入IN参数,也有输出OUT参数,输出是简单值(非列表)
 
存储过程 TEST_MICHAEL 的SQL如下:
Sql代码  


  • CREATE OR REPLACE PROCEDURE TEST_MICHAEL(P_USERID IN VARCHAR2,  
  •                                          P_SALARY IN NUMBER,  
  •                                          P_COUNT  OUT NUMBER) IS  
  •   V_SALARY NUMBER := P_SALARY;  
  • BEGIN  
  •   IF V_SALARY IS NULL THEN  
  •     V_SALARY := 0;  
  •   END IF;  
  •   IF P_USERID IS NULL THEN  
  •     SELECT COUNT(*)  
  •       INTO P_COUNT  
  •       FROM TMP_MICHAEL T  
  •      WHERE T.SALARY >= V_SALARY;  
  •   ELSE  
  •     SELECT COUNT(*)  
  •       INTO P_COUNT  
  •       FROM TMP_MICHAEL T  
  •      WHERE T.SALARY >= V_SALARY  
  •        AND T.USER_ID LIKE '%' || P_USERID || '%';  
  •   END IF;  
  •   DBMS_OUTPUT.PUT_LINE('v_count=:' || P_COUNT);  
  • END TEST_MICHAEL;  

  调用程序如下:
Java代码  


  • /** 
  •     * 测试调用存储过程:返回值是简单值非列表 
  •     * @blog http://sjsky.iyunv.com 
  •     * @author Michael 
  •     * @throws Exception 
  •     */  
  •    public static void testProcOutSimple() throws Exception {  
  •        System.out.println("-------  start 测试调用存储过程:返回值是简单值非列表");  
  •        Connection conn = null;  
  •        CallableStatement stmt = null;  
  •        try {  
  •            Class.forName(DB_DRIVER);  
  •            conn = DriverManager.getConnection(DB_CONNECTION, DB_NAME, DB_PWd);  
  •   
  •            stmt = conn.prepareCall("{call TEST_MICHAEL(?,?,?)}");  
  •   
  •            stmt.setString(1"");  
  •            stmt.setDouble(23000);  
  •   
  •            // out 注册的index 和取值时要对应  
  •            stmt.registerOutParameter(3, Types.INTEGER);  
  •            stmt.execute();  
  •   
  •            // getXxx(index)中的index 需要和上面registerOutParameter的index对应  
  •            int i = stmt.getInt(3);  
  •            System.out.println("符号条件的查询结果 count := " + i);  
  •            System.out.println("-------  Test End.");  
  •        } catch (Exception e) {  
  •            e.printStackTrace(System.out);  
  •        } finally {  
  •            if (null != stmt) {  
  •                stmt.close();  
  •            }  
  •            if (null != conn) {  
  •                conn.close();  
  •            }  
  •        }  
  •    }  

   测试程序就是查询薪水3000以上人员的数量 ,运行结果如下:
------- start 测试调用存储过程:返回值是简单值非列表
符号条件的查询结果 count := 4
------- Test End.
 
[三]、既有输入IN参数,也有输出OUT参数,输出是列表
  首先需要创建PACKAGE TEST_PKG_CURSOR 的SQL如下:
Sql代码  


  • CREATE OR REPLACE PACKAGE TEST_PKG_CURSOR IS  
  •   
  •   -- Author  : MICHAEL  http://sjsky.iyunv.com  
  •   TYPE TEST_CURSOR IS REF CURSOR;  
  •   
  • END TEST_PKG_CURSOR;  

再创建存储过程 TEST_P_OUTRS 的SQL如下:
Sql代码  


  • CREATE OR REPLACE PROCEDURE TEST_P_OUTRS(P_SALARY IN NUMBER,  
  •                                          P_OUTRS  OUT TEST_PKG_CURSOR.TEST_CURSOR) IS  
  •   V_SALARY NUMBER := P_SALARY;  
  • BEGIN  
  •   IF P_SALARY IS NULL THEN  
  •     V_SALARY := 0;  
  •   END IF;  
  •   OPEN P_OUTRS FOR  
  •     SELECT * FROM TMP_MICHAEL T WHERE T.SALARY > V_SALARY;  
  • END TEST_P_OUTRS;  

 调用存储过程的代码如下:
Java代码  


  • /** 
  •     * 测试调用存储过程:有返回值且返回值为列表的 
  •     * @blog http://sjsky.iyunv.com 
  •     * @author Michael 
  •     * @throws Exception 
  •     */  
  •    public static void testProcOutRs() throws Exception {  
  •        System.out.println("-------  start 测试调用存储过程:有返回值且返回值为列表的");  
  •        Connection conn = null;  
  •        CallableStatement stmt = null;  
  •        ResultSet rs = null;  
  •        try {  
  •            Class.forName(DB_DRIVER);  
  •            conn = DriverManager.getConnection(DB_CONNECTION, DB_NAME, DB_PWd);  
  •   
  •            stmt = conn.prepareCall("{call TEST_P_OUTRS(?,?)}");  
  •   
  •            stmt.setDouble(13000);  
  •            stmt.registerOutParameter(2, OracleTypes.CURSOR);  
  •            stmt.execute();  
  •   
  •            // getXxx(index)中的index 需要和上面registerOutParameter的index对应  
  •            rs = (ResultSet) stmt.getObject(2);  
  •            // 获取列名及类型  
  •            int colunmCount = rs.getMetaData().getColumnCount();  
  •            String[] colNameArr = new String[colunmCount];  
  •            String[] colTypeArr = new String[colunmCount];  
  •            for (int i = 0; i < colunmCount; i++) {  
  •                colNameArr = rs.getMetaData().getColumnName(i + 1);  
  •                colTypeArr = rs.getMetaData().getColumnTypeName(i + 1);  
  •                System.out.print(colNameArr + "(" + colTypeArr + ")"  
  •                        + " | ");  
  •            }  
  •            System.out.println();  
  •            while (rs.next()) {  
  •                StringBuffer sb = new StringBuffer();  
  •                for (int i = 0; i < colunmCount; i++) {  
  •                    sb.append(rs.getString(i + 1) + " | ");  
  •                }  
  •                System.out.println(sb);  
  •            }  
  •            System.out.println("------- Test Proc Out is ResultSet end. ");  
  •   
  •        } catch (Exception e) {  
  •            e.printStackTrace(System.out);  
  •        } finally {  
  •            if (null != rs) {  
  •                rs.close();  
  •            }  
  •            if (null != stmt) {  
  •                stmt.close();  
  •            }  
  •            if (null != conn) {  
  •                conn.close();  
  •            }  
  •        }  
  •    }  

 运行结果如下:
------- start 测试调用存储过程:有返回值且返回值为列表的
USER_ID(VARCHAR2) | USER_NAME(VARCHAR2) | SALARY(NUMBER) | OTHER_INFO(VARCHAR2) | 
michael | Michael | 5000 | null | 
zhangsan | 张三 | 10000 | null | 
aoi_sola | 苍井空 | 99999.99 | null | 
jdbc | JDBC | 8000 | http://sjsky.iyunv.com | 
------- Test Proc Out is ResultSet end.
 [四]、输入输出参数是同一个(IN OUT)
 
创建存储过程TEST_P_INOUT 的SQL如下:
Sql代码  


  • CREATE OR REPLACE PROCEDURE TEST_P_INOUT(P_USERID IN VARCHAR2,  
  •                                          P_NUM    IN OUT NUMBER) IS  
  •   V_COUNT  NUMBER;  
  •   V_SALARY NUMBER := P_NUM;  
  • BEGIN  
  •   IF V_SALARY IS NULL THEN  
  •     V_SALARY := 0;  
  •   END IF;  
  •   
  •   SELECT COUNT(*)  
  •     INTO V_COUNT  
  •     FROM TMP_MICHAEL  
  •    WHERE USER_ID LIKE '%' || P_USERID || '%'  
  •      AND SALARY >= V_SALARY;  
  •   P_NUM := V_COUNT;  
  • END TEST_P_INOUT;  

 调用存储过程的代码:
Java代码  


  • /** 
  •      * 测试调用存储过程: INOUT同一个参数: 
  •      * @blog http://sjsky.iyunv.com 
  •      * @author Michael 
  •      * @throws Exception 
  •      */  
  •     public static void testProcInOut() throws Exception {  
  •         System.out.println("-------  start 测试调用存储过程:INOUT同一个参数");  
  •         Connection conn = null;  
  •         CallableStatement stmt = null;  
  •         try {  
  •             Class.forName(DB_DRIVER);  
  •             conn = DriverManager.getConnection(DB_CONNECTION, DB_NAME, DB_PWd);  
  •   
  •             stmt = conn.prepareCall("{call TEST_P_INOUT(?,?)}");  
  •   
  •             stmt.setString(1"michael");  
  •             stmt.setDouble(23000);  
  •   
  •             // 注意此次注册out 的index 和上面的in 参数index 相同  
  •             stmt.registerOutParameter(2, Types.INTEGER);  
  •             stmt.execute();  
  •   
  •             // getXxx(index)中的index 需要和上面registerOutParameter的index对应  
  •             int count = stmt.getInt(2);  
  •             System.out.println("符号条件的查询结果 count := " + count);  
  •             System.out.println("-------  Test End.");  
  •         } catch (Exception e) {  
  •             e.printStackTrace(System.out);  
  •         } finally {  
  •             if (null != stmt) {  
  •                 stmt.close();  
  •             }  
  •             if (null != conn) {  
  •                 conn.close();  
  •             }  
  •         }  
  •     }  

 运行结果如下:
------- start 测试调用存储过程:INOUT同一个参数
符号条件的查询结果 count := 1
------- Test End.
 
到处基本介绍已经结束了,希望能给大家有所帮助。
 
 
本文连接:http://sjsky.iyunv.com/blog/1246657
 
 
转载请注明来自:Michael's blog @ http://sjsky.iyunv.com




运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-250748-1-1.html 上篇帖子: 数据库基本函数——数字函数(Oracle) 下篇帖子: Oracle作业job 没有自动调度起来
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表