Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
找到字符串,在从Java调用的Oracle函数中应为数字_Java_Oracle_Function_Package - Fatal编程技术网

找到字符串,在从Java调用的Oracle函数中应为数字

找到字符串,在从Java调用的Oracle函数中应为数字,java,oracle,function,package,Java,Oracle,Function,Package,编辑 把这个放在这里,以防它对其他人有帮助。我的问题是未能理解PreparedStatement是如何工作的。我相信“?”…setInt()语法是一个简单的替换,它构造一个SQL语句,解释它并将其发送到DB,但事实并非如此。下面的答案详细解释了这个问题 原始问题 我在Java应用程序中执行Oracle包函数调用时遇到一些问题。我收到以下错误: ORA-01858: a non-numeric character was found where a numeric was expected 我相

编辑

把这个放在这里,以防它对其他人有帮助。我的问题是未能理解PreparedStatement是如何工作的。我相信“?”…setInt()语法是一个简单的替换,它构造一个SQL语句,解释它并将其发送到DB,但事实并非如此。下面的答案详细解释了这个问题

原始问题

我在Java应用程序中执行Oracle包函数调用时遇到一些问题。我收到以下错误:

ORA-01858: a non-numeric character was found where a numeric was expected
我相信我已经正确构造了调用,并且我使用字符串的唯一位置是日期字段(不是数字字段)。该函数具有以下签名:

function f_get_mr_target(a_plan_id number,a_machine number,a_shift_id number,a_shift_dt date) return number;
我调用函数的java代码如下所示:

public Double checkMRTarget(int planId, int machineNum, int shiftId, String date)
{
    //Instantiate the return value
    Double mrTarget = null;

    //Get the MR target
    try
    {
        //Ready the connection
        con = nativeDataSource.getConnection();

        //The query string
        String sql = "select pkg_bcs.f_get_mr_target(?,?,?,?) target from dual";

        //Prepare the query
        stmt = null;
        stmt = con.prepareStatement(sql);
        stmt.setInt(1, planId);
        stmt.setInt(2, machineNum);
        stmt.setInt(3, shiftId);
        stmt.setString(4, date);

        //Execute the query
        ResultSet rs = stmt.executeQuery();

        //Extract the value from the result set
        mrTarget = rs.getDouble("target");
    }
    catch (Throwable e)
    { 
        System.out.println("Error getting mrTarget: " + e); 
    }
    finally
    { closeDBConnections(); }

    //Return the value
        return mrTarget;
}
planId = 986548
machineNum = 5227
shiftId = 10
date = "trunc(sysdate)"
Con是类中所有其他方法共享的公共连接对象。Stmt是一个PreparedStatement对象,也是共享的。参数传递如下:

public Double checkMRTarget(int planId, int machineNum, int shiftId, String date)
{
    //Instantiate the return value
    Double mrTarget = null;

    //Get the MR target
    try
    {
        //Ready the connection
        con = nativeDataSource.getConnection();

        //The query string
        String sql = "select pkg_bcs.f_get_mr_target(?,?,?,?) target from dual";

        //Prepare the query
        stmt = null;
        stmt = con.prepareStatement(sql);
        stmt.setInt(1, planId);
        stmt.setInt(2, machineNum);
        stmt.setInt(3, shiftId);
        stmt.setString(4, date);

        //Execute the query
        ResultSet rs = stmt.executeQuery();

        //Extract the value from the result set
        mrTarget = rs.getDouble("target");
    }
    catch (Throwable e)
    { 
        System.out.println("Error getting mrTarget: " + e); 
    }
    finally
    { closeDBConnections(); }

    //Return the value
        return mrTarget;
}
planId = 986548
machineNum = 5227
shiftId = 10
date = "trunc(sysdate)"
我已经证实了这一点

select pkg_bcs.f_get_mr_target(986548, 5227, 10, trunc(sysdate)) target from dual;

在SQLDeveloper中工作得很好。据我所知,它得到了一个数字,它期望一个数字

第四个参数是date,不能与字符串一起工作。它等待一个日期对象

这是您的方法签名,传递日期对象而不是字符串

public Double checkMRTarget(int planId, int machineNum, int shiftId, Date date)

您调用了
setString
,因此Java发送了一个Oracle无法隐式转换为
日期的
字符串

您可以将其转换为
java.sql.Date
java.sql.Time
java.sql.Timestamp
,方法是首先用a解析日期,并创建适当的对象,然后调用
setDate
setTime
setTimestamp
,而不是
setString

或者,您可以通过调用JDBC SQL让Oracle对其进行转换:

// Your date format may vary.
String sql = "select pkg_bcs.f_get_mr_target(?,?,?,to_date(?, 'YYYY-MM-DD')) target from dual";

将字符串数据类型替换为日期参数是一场灾难。在这种情况下(在您的代码上下文中),它肯定会出现
ORA-01858
异常

参数替换需要精确绑定,这是为了实现强类型的目的。 请将第四个参数,即
字符串
参数转换为
日期对象
&然后实现你想要的。那就行了


此外,SQL查询中的
trunc(sysdate)
不会向SQL客户端返回字符串。而是返回日期(内部转换)。这是为了使解析器能够高效且一致地识别日期类型而设计的。

您为什么认为可以将字符串
trunc(sysdate)
传递给需要日期类型的参数?参数替换是强类型的,您不能只为
Date
参数传递任意SQL文本。这显然是对PreparedStatement工作原理的误解。谢谢你有条理地解释了这个问题!