JDBC(四)—CallableStatement执行匿名块

背景

记录JDBC一系列的内容,实际上这章才是我在项目中遇到的问题,也是因为这个问题,我才想看看JDBC的内容,虽然这部分杜老师并没有提到过,但是如果想解决这部分的东西,也需要前面的铺垫,毕竟所有东西都是由简到难。项目中使用jdbc动态的连接数据库,主要是为了做一些操作,然后分析返回的结果,而遇到的问题就是如何返回结果参数。

问题

项目是由好几个人开发的,原本这部分是别人开发的,用python写的,但是由于种种原因需要我根据他的逻辑重新用java写一遍,问题来了

  result = cursor.execute(query_sql, other_xml=other_xml)
  l_other_xml = other_xml.getvalue()

这个sql是个匿名块(不懂的也可以理解是存储过程的简化版),取执行sql的同时,还传了参数,用来返回在sql中执行的结果,网上执行存储过程,存储函数的方法一大堆,匿名块找不到,一开始没办法,打算把匿名块改成存储过程,结果被告知,客户是不允许我们在库里定义存储过程的,尴尬了。

解决方法

  • 首先看下匿名块
BEGIN
                    FOR i IN (SELECT other_xml
                                FROM dba_hist_sql_plan
                            WHERE sql_id = TRIM('%s')
                                AND plan_hash_value = TO_NUMBER(TRIM('%s'))
                                AND other_xml IS NOT NULL
                            ORDER BY
                                    id)
                    LOOP
                        :other_xml := i.other_xml;
                        EXIT;
                    END LOOP;
                EXCEPTION
                    WHEN OTHERS THEN
                        DBMS_OUTPUT.PUT_LINE('getting other_xml from awr: '||SQLERRM);
                        :other_xml := NULL;
                END;

具体执行了什么也不懂,DBA写的,但是现在需求是获取到最后的other_xml的值,

  • 改写sql
        declare \n" +
                                "  other_xml CLOB;\n" +
                                "          \n" +
                                "             BEGIN\n" +
                                "                FOR i IN (SELECT other_xml\n" +
                                "                            FROM gv$sql_plan\n" +
                                "                            WHERE sql_id = TRIM(?)\n" +
                                "                            AND plan_hash_value = TO_NUMBER(TRIM(?))\n" +
                                "                            AND other_xml IS NOT NULL\n" +
                                "                            ORDER BY\n" +
                                "                                child_number, id)\n" +
                                "                LOOP\n" +
                                "                    other_xml := i.other_xml;\n" +
                                "                    EXIT;\n" +
                                "                END LOOP;\n" +
                                "               ?:=other_xml;\n" +
                                "            EXCEPTION\n" +
                                "                WHEN OTHERS THEN\n" +
                                "                    DBMS_OUTPUT.PUT_LINE('getting other_xml from memory: '||SQLERRM);\n" +
                                "                    other_xml := NULL;\n" +
                                "            END;

如果你仔细的看,这里加了个

?:=other_xml;

看到问号,会想到什么?
这里的sql03就是上面的改写过的sql

CallableStatement call3 = connect.prepareCall(sql03);
                call3.setString(1,sqlId);
                call3.setString(2,planHashValue);
                call3.registerOutParameter(3,OracleTypes.CLOB);
                call3.execute();
                Clob other_xml=call3.getClob(3);

你仔细看,是有三个问号,代表个参数,第一个和第二个都代表的是传入参数,第三个代表的是返回参数,CallableStatement可以设置注册返回参数,下标根据?的位置来,这里并不区分传入的还是传出的,我一开始认为第一个传出的就是下标1和传入的不关联,结果就错了,然后通过get下标来获取,这里有个固定就是,传入和获取要么都使用下标,要么都是用名字。当然CallableStatement这个也可以执行存储过程和函数,但是这个网上一大堆,就不写了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值