从Java传递日期值的字符
任何人有想法如何解决这个问题?
注意:模拟步骤在本主题的最后部分。
目前我在plsql程序的这行代码中接收异常ORA-01877:字符串对于内部缓冲区来说太长了
v_old_val := TO_CHAR (p_val);
p_val被声明为TIMESTAMP,当表中有新的记录被插入或从Java应用程序更新时,值从触发器传递。
进行一些调试后,我发现只有满足以下条件时才会发生此问题:
应用程序将该记录插入到该表格中,并在1978年之前的日期
客户端的时区是亚洲/上海
应用程序服务器和数据库服务器中的时区是亚洲/新加坡
从应用程序日志捕获的示例数据
客户端>> Thu Jul 27 00:00:00 CST 1978(用户键入日期)
服务器端>> Wed Jul 26 23:30:00 SGT 1978(插入db的日期)
PLSQL功能
PROCEDURE writelog_t (
p_val IN TIMESTAMP
)
IS
BEGIN
v_old_val := TO_CHAR (p_val);
END
表
CREATE TABLE birthday(
KEY NUMBER(12) NOT NULL,
birth_dt TIMESTAMP(6)
)
触发
CREATE OR REPLACE TRIGGER "BIRTHDAY_TRG"
AFTER DELETE OR INSERT OR UPDATE
ON BIRTHDAY
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
BEGIN
IF NOT DELETING THEN
plsql_prod.Writelog_t(:NEW.BIRTH_DT);
END IF;
END
更新:我曾尝试将引起问题的行注释掉,并将数据提交到工作表中。 但是,当我尝试通过使用Toad(版本8.6.1.0)查询插入的数据时,Toad显示相同的错误并崩溃。
SELECT TO_CHAR(birth_dt) FROM working_table
ORA-01877:字符串对于内部缓冲区来说太长
调用堆栈
模拟
我发现了一种模拟这个问题的方法。
CREATE TABLE birthday(
KEY NUMBER(12) NOT NULL,
birth_dt TIMESTAMP(6)
)
示例Java程序
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
public class TimeZoneTestCase {
private static final String DATE_FORMAT = "dd-M-yyyy hh:mm:ss a";
public static void main(String[] args) {
String dateInString = "27-07-1978 12:00:00 AM";
SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT);
try {
// connection is the data source we used to fetch the data from
Connection connection = establishConnection();
Statement statement = connection.createStatement();
PreparedStatement updateTotal = connection
.prepareStatement("INSERT INTO birthday (key, birth_dt) VALUES (0,?)");
statement
.executeUpdate("INSERT INTO birthday (key, birth_dt) VALUES (0, TIMESTAMP '1978-07-27 00:00:00 Asia/Singapore')");
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
Date date = formatter.parse(dateInString);
System.out.println("Date (CST) : " + date);
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Singapore"));
Calendar calendar = new GregorianCalendar();
calendar.setTime(date);
System.out.println("Date (SGT) : " + calendar.getTime());
updateTotal.setTimestamp(1, new Timestamp(calendar.getTimeInMillis()));
updateTotal.executeUpdate();
updateTotal.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection establishConnection() {
Connection conn = null;
try {
Class.forName("oracle.jdbc.OracleDriver");
String db2URL = "Please fill in your db url here";
String userName = "Please fill in your db login username";
String password = "Please fill in your db login password";
conn = DriverManager.getConnection(db2URL, userName, password);
conn.setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return conn;
}
}
然后在db中运行,那么你会得到这个问题
select * from birhtday