我正在尝试使用Oracle存储过程来更新数据库表。我从Java程序调用该过程。我希望我的程序接受格式为'01 -01-2015'的日期,但由于某种原因,我的程序只接受格式为'01 -JAN-2015'的日期。
我的存储过程:
DELIMITER //
CREATE OR REPLACE PROCEDURE updateAward
(
p_award_id IN awards.award_id%TYPE,
p_award_date IN awards.award_date%TYPE,
p_total_amount IN awards.total_amount%TYPE,
p_number_sales IN awards.number_sales%TYPE,
p_emp_id IN awards.emp_id%TYPE
)
AS
BEGIN
UPDATE awards
SET award_date = to_date(p_award_date, 'DD-MM-YYYY'),
total_amount = p_total_amount,
number_sales = p_number_sales,
emp_id = p_emp_id
WHERE award_id = p_award_id;
COMMIT;
END;
/
调用它的java代码:
public boolean updateByID(Connection conn, String strVar, int[] intVar, double doubleVar)
{
System.out.println(strVar);
System.out.println(doubleVar);
System.out.println(intVar[0]);
System.out.println(intVar[1]);
System.out.println(intVar[2]);
try
{
String query = "{call updateAward(?,?,?,?,?)}";
CallableStatement stmt = conn.prepareCall(query);
stmt.setInt(1,intVar[0]);
stmt.setString(2, strVar);
stmt.setDouble(3, doubleVar);
stmt.setInt(4, intVar[1]);
stmt.setInt(5, intVar[2]);
stmt.executeUpdate();
return true;
}
catch(SQLException e)
{
System.out.println(e.getMessage());
}
return false;
}
控制台打印出传递的变量:
12-12-2012
65165.2
21
22
3
错误本身:
KORA-01843: not a valid month
ORA-06512: at line 1
我找到的每个解决方案都是将日期格式放在过程中。我相信我已经用
完成了award_date = to_date(p_award_date, 'DD-MM-YYYY'),
我写错了吗?有人可以帮忙吗?
答案 0 :(得分:1)
目前您正在传递字符串:
stmt.setString(2, strVar);
你正在解析一个字符串:
award_date = to_date(p_award_date, 'DD-MM-YYYY')
但您希望自定义类型中包含日期,这就是转换失败的地方。将其更改为VARCHAR(或VARCHAR2),它将起作用。
答案 1 :(得分:1)
您正在通过setString()
将字符串传递给期望Oracle日期参数的过程。这意味着在您到达to_date()
电话之前,Oracle必须使用会话/区域设置NLS_DATE_FORMAT将字符串隐式转换为日期作为通话的一部分。
您可以将过程参数类型从awards.award_date%TYPE
更改为varchar2
,并且仍然可以在过程中进行显式转换。或者您可以保留过程签名,并通过在Java端转换它来传递正确的数据类型,例如:
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
cStmt.setDate(2, new java.sql.Date(sdf.parse(strVar).getTime()));
由于p_date
已经是日期,因此您不应该在其上调用to_date()
,因为它会将隐式转换回字符串(再次使用NLS_DATE_FORMAT),然后尝试显式转换使用您提供的格式模型返回日期,这也可能会产生类似的错误。简化为:
SET award_date = p_award_date,