【问题标题】:Passing a list of dates to an oracle db function via java通过java将日期列表传递给oracle db函数
【发布时间】:2017-09-23 09:08:32
【问题描述】:

我需要将日期列表传递给数据库函数,并比较所选日期是否属于正在传递的这些假期的列表。我的数据库功能目前如下。需要将动态假期列表作为输入参数传递给此函数,并检查 START_DATE 是否也在该假期列表中。

create or replace 
FUNCTION getWorkingDays (DATE_ONE DATE, DATE_TWO DATE) RETURN NUMBER
IS
DAY_COUNT NUMBER := 0;
START_DATE DATE;
END_DATE DATE;
BEGIN -- loop through and update
IF(DATE_ONE is not null and DATE_TWO is not null)
THEN
IF DATE_ONE < DATE_TWO THEN
  START_DATE := DATE_ONE;
  END_DATE := DATE_TWO;
ELSE
  START_DATE := DATE_TWO;
  END_DATE := DATE_ONE;
END IF;

WHILE START_DATE < END_DATE
LOOP
  IF TO_CHAR(START_DATE,'DY') NOT IN ('SAT','SUN') THEN
    DAY_COUNT := DAY_COUNT + 1;
END IF;
  START_DATE := START_DATE + 1;
END LOOP;
END IF;
RETURN DAY_COUNT;
EXCEPTION
WHEN OTHERS THEN
RETURN NULL;
END getWorkingDays;

【问题讨论】:

  • 那么,问题是什么?
  • 如何将日期列表作为输入参数传递给 DB 函数以及如何比较开始日期是否在函数内的该日期内?
  • 查看this question 了解您问题的第一部分。问题的第二部分是算法开发,这超出了 SO 问题的范围。

标签: java oracle


【解决方案1】:

将数组传递给数据库函数有很多方法。一个简单的如下:

首先你应该在你的数据库架构中创建一个TABLE 类型:

CREATE TYPE DATE_ARRAY AS TABLE OF DATE;

之后你应该用这种新的输入类型写一个FUNCTION

-- a dummy function just for presenting the usage of input array
CREATE FUNCTION Date_Array_Test_Function(p_data IN DATE_ARRAY) 
RETURN INTEGER  
IS
    TYPE Cur IS REF CURSOR;
    MyCur cur;

    single_date DATE;
BEGIN
    /* Inside this function you can do anything you wish 
        with the input parameter: p_data */

    OPEN MyCur FOR SELECT * FROM table(p_data);

    LOOP
      FETCH MyCur INTO single_date;
      EXIT WHEN MyCur%NOTFOUND;

      dbms_output.put_line(to_char(single_date));
    END LOOP;

    RETURN 0;

END Date_Array_Test_Function;

现在在java 代码中,您可以使用以下代码调用具有数组输入类型的此类函数:

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Types;

import oracle.sql.ARRAY;
import oracle.sql.ArrayDescriptor;

public class Main 
{           
    public static void main(String[] args) throws SQLException 
    {
        Connection c = DriverManager.getConnection(url, user, pass);

        String query = "begin ? := date_array_test_function( ? ); end;";

        // note the uppercase "DATE_ARRAY"
        ArrayDescriptor arrDescriptor = ArrayDescriptor.createDescriptor("DATE_ARRAY", c);

        // Test dates
        Date[] inputs = new Date[] {new Date(System.currentTimeMillis()),
                                    new Date(System.currentTimeMillis()),
                                    new Date(System.currentTimeMillis())};

        ARRAY array = new ARRAY(arrDescriptor, c, inputs);

        CallableStatement cs = c.prepareCall(query);
        cs.registerOutParameter(1, Types.INTEGER); // the return value
        cs.setObject(2, array); // the input of the function
        cs.executeUpdate();

        System.out.println(cs.getInt(1));
    }
}

希望这会有所帮助。

祝你好运

【讨论】:

    【解决方案2】:
    CREATE TYPE DateList IS TABLE OF DATE;
    /
    
    CREATE FUNCTION getWorkingDays (
      in_start_date IN  DATE,
      in_end_date   IN  DATE,
      in_date_list  IN  DateList
    ) RETURN NUMBER
    IS
      p_start_date   DATE;
      p_end_date     DATE;
      p_working_days NUMBER;
    BEGIN
      IF in_start_date IS NULL OR in_end_date IS NULL THEN
        RETURN NUll;
      END IF;
    
      p_start_date := TRUNC( LEAST( in_start_date, in_end_date ) );
      p_end_date   := TRUNC( GREATEST( in_start_date, in_end_date ) );
    
      -- 5/7 * ( Number of days between monday of the week containing the start date
      --         and monday of the week containing the end date )
      -- + LEAST( day of week for end date, 5 )
      -- - LEAST( day of week for start date, 5 )
      p_working_days := ( TRUNC( p_end_date, 'IW' ) - TRUNC( p_start_date, 'IW' ) ) * 5 / 7
                        + LEAST( p_end_date - TRUNC( p_end_date, 'IW' ) + 1, 5 )
                        - LEAST( p_start_date - TRUNC( p_start_date, 'IW' ) + 1, 5 );
    
      IF in_date_list IS NOT NULL THEN
        FOR i IN 1 .. in_date_list.COUNT LOOP
          IF in_date_list(i) >= p_start_date AND in_date_list(i) < p_end_date THEN
            p_working_days := p_working_days - 1;
          END IF;
        END LOOP;
      END IF;
    
      RETURN p_working_days;
    END;
    /
    

    @STaefi 有一个如何将数组传递给过程的示例。还有其他示例,例如:“How to pass List from java to Oracle Procedure?”。

    【讨论】:

      猜你喜欢
      • 2015-02-22
      • 2013-11-25
      • 1970-01-01
      • 1970-01-01
      • 2014-05-02
      • 2017-01-15
      • 2019-06-26
      • 2016-06-24
      • 2023-04-03
      相关资源
      最近更新 更多