Java调用程序oracle plsql返回没有数据但在plsql中返回数据

时间:2016-07-21 02:35:33

标签: java oracle function plsql procedure

我有一个函数plsql,在plsql中运行函数返回游标有数据但我在java中调用这个函数问题返回resultset falase帮我解决这个问题

enter code here

这个函数plsql

FUNCTION get_canh_bao(
        p_toolid        in  varchar2)
      RETURN  sys_refcursor IS

        s           varchar2(4000);
        ptype       varchar2(1000);
        pday        varchar2(1000);
        psql        varchar2(1000);
        pcreate     varchar2(1000);
        re          sys_refcursor;
        pwhere      varchar2(1000);
    BEGIN
    --
        pwhere := '';
        s := 'select b.TYPE_REPORT, b.DAY_NHAPLIEU, a.sql_cmd, a.name_createdate'
            ||' from cpcdata.tbl_config_nhaplieu a'
            ||' left join cpcdata.tbl_mainmenu b'
            ||' on a.tool_id = b.ID '
            ||' where b.show_all = 0 and b.flag = 1 and b.ID = :toolid';
        execute immediate s INTO ptype, pday, psql, pcreate using p_toolid;
                -- Tinh ngay canh bao
                if (INSTR(psql,'where') > 0 ) then
                    pwhere := ' and ';
                else
                    pwhere := ' where ';
                end if;
                s := psql ||pwhere||pcreate||' between :aDate AND :bDate';
                CASE
                    WHEN ptype = 'day'    THEN
                        s := psql ||pwhere|| ' to_char('||pcreate||',''dd/mm/yyyy'') = to_char(sysdate - '||pday||',''dd/mm/yyyy'')';
                        open re for s;
                    WHEN ptype = 'week'   THEN
                        open re for s USING TRUNC (sysdate, 'iw'), TRUNC(sysdate, 'iw') + 7 - 1/86400- pday;
                    WHEN ptype = 'month'  THEN
                        open re for s USING TRUNC (sysdate, 'mm'), to_date(LAST_DAY(TRUNC (sysdate, 'mm')) + 1 - 1/86400 - pday,'dd/mm/yyyy');
                    WHEN ptype = 'quy'    THEN
                        open re for s USING TRUNC (sysdate, 'Q'), to_date(add_months(trunc(sysdate,'Q'),3)- 1 - pday, 'dd/mm/yyyy');
                    WHEN ptype = 'year'   THEN
                        open re for s USING TRUNC (sysdate , 'YEAR'), to_date(ADD_MONTHS(TRUNC (SYSDATE,'YEAR'),12) - 1 - pday, 'dd/mm/yyyy');
                    ELSE return null;
                END CASE;
        dbms_output.put_line(''||s);
        RETURN re ;
        exception when others then
            declare
                s_err       varchar2(2000);
                str         varchar(2000);
                c_err       sys_refcursor;
            begin
                s_err := 'loi khi lay du lieu '|| sqlerrm;
                str := 'select '||s_err||' from dual';
                open c_err for str;
                return c_err;
            end;
    END;

这是代码java

  Class.forName("oracle.jdbc.driver.OracleDriver");
  Connection conn =
      DriverManager.getConnection("jdbc:oracle:thin:@***:**:**",
                                  "***", "***");
  System.out.println("Connect db success ! ");
ArrayList arr = new ArrayList();
            String sql = "{? = call get_canh_bao(?)}";
            CallableStatement cs = conn.prepareCall(sql);
            cs.registerOutParameter(1, OracleTypes.CURSOR);
            cs.setString(2, "502");
            cs.executeQuery();
            ResultSet rs = (ResultSet)cs.getObject(1);
            System.out.println("------------ResultSet---------------"+rs.next());
            while (rs.next()) {

              System.out.println("a");
              String[] str =
              {"1" };
              arr.add(str);
            }

  System.out.println("size="+arr.size());

在java中运行代码时的结果

Connect db success ! 
------------ResultSet---------------false
size=0

2 个答案:

答案 0 :(得分:1)

问题可能是由使用隐式日期格式的日期转换之一引起的。

Oracle没有“默认”日期格式,日期格式始终取决于客户端。您的Java客户端和数据库IDE可能具有不同的默认值。

通过更改客户端设置来修复代码。而是清理日期函数并删除所有日期到字符转换。

通常,在处理日期时,几乎应始终避免使用TO_DATETO_CHAR。如果需要操纵日期,几乎肯定有日期功能  这不需要转换。并且日期应始终存储为日期,因此您不需要在表格中来回转换。

最大的问题可能是:

    pcreate     varchar2(1000);

将其更改为日期。如果由于某种原因a.name_createdate是一个字符串,那么至少要明确转换。

答案 1 :(得分:0)

您从pcreate填充tbl_config_nhaplieu.name_createdate(字符串)而未指定格式,因此(假设它是date列)格式可能是在Java客户端环境中不同,例如如果默认为mm/dd/yyyydd-mon-yyyy而非dd/mm/yyyy

稍后您将其直接与日期进行比较:

s := psql || pwhere || pcreate || ' between :aDate and :bDate';

但没有引用,所以你会得到这样的查询:

where 01/02/2016 between :aDate and nDate

在其他地方,您将其转换回假定为dd/mm/yyyy格式的日期(您之前未将其编码为字符串时未指定,因此没有理由应该匹配该格式) :

s := psql || pwhere || ' to_char(' || pcreate || ',''dd/mm/yyyy'') = to_char(sysdate - ' || pday || ',''dd/mm/yyyy'')';

但它也没有引用,所以你会得到这样的东西:

where to_char(01/02/2016,'dd/mm/yyyy') = to_char(sysdate - 3,'dd/mm/yyyy')

会失败。

然后就是这样:

to_date(last_day(trunc(sysdate,'mm')) + 1 - 1 / 86400 - pday, 'dd/mm/yyyy')

可能无法给出您期望的结果。例如:

select to_date(last_day(trunc(sysdate,'mm')) + 1 - 1 / 86400 - 0, 'dd/mm/yyyy') as test
from dual;
由于31-JUL-2016设置不同,

在SQL * Plus和SQL Developer中为31/07/0016但在PL / SQL Developer中为nls_date_parameter

正如乔恩所说,你需要清理所有日期处理。