2016-07-21 114 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所說,你需要清理所有的日期處理。