2016-07-21 115 views
0

我有一个功能PLSQL,运行功能PLSQL返回游标有数据,但我调用java的问题返回结果集falase这个功能帮我处理问题,这Java调用程序的Oracle PLSQL不返回数据,但在PLSQL返回数据

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 
+0

你有没有注意到你在System.out.println中前进到第一条记录,并在while循环中取下一条记录 - 如果有的话。 –

回答

1

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

Oracle没有“默认”日期格式,日期格式总是依赖于客户端。您的Java客户端和数据库IDE可能具有不同的默认值。

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

一般来说,使用日期时,几乎总是应该避免使用TO_DATETO_CHAR。如果需要操作日期,几乎可以肯定有一个不需要转换的日期函数 。日期应该始终保存为日期,所以你不需要在表格中来回转换。

最大的问题大概是这样的:

pcreate  varchar2(1000); 

变化,为一个日期。如果由于某种原因a.name_createdate是一个字符串,那么至少使转换显式化。

+0

谢谢你,但pcreate的表类型varchar。此外,我的事情问题不在这里。 –

+0

在程序函数plsql中:当运行函数返回数据时 –

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; 

这给了我在SQL * Plus 31-JUL-2016和SQL开发人员,但在31/07/0016 PL/SQL Developer中,由于不同的nls_date_parameter设置。正如Jon所说,你需要清理所有的日期处理。