Chúng tôi đang cố gắng lưu trữ một chuỗi mã hóa UTF-16 vào cơ sở dữ liệu Oracle AL32UTF8.Bộ ký tự JDBC Oracle và giới hạn 4000 char
Chương trình của chúng tôi hoạt động hoàn hảo trên cơ sở dữ liệu sử dụng WE8MSWIN1252
làm bộ ký tự. Khi chúng tôi cố gắng chạy nó trên một cơ sở dữ liệu sử dụng AL32UTF8
nó được một java.sql.SQLException: ORA-01461: can bind a LONG value only for insert into a LONG column
.
Trong testcase dưới đây mọi thứ hoạt động tốt miễn là dữ liệu đầu vào của chúng tôi không quá dài.
Chuỗi đầu vào có thể vượt quá 4000 ký tự. Chúng tôi muốn giữ lại càng nhiều thông tin càng tốt, mặc dù chúng tôi nhận ra rằng đầu vào sẽ bị cắt bỏ.
Bảng cơ sở dữ liệu của chúng tôi được xác định bằng cách sử dụng từ khóa CHAR
(xem bên dưới). Chúng tôi hy vọng rằng điều này sẽ cho phép chúng tôi lưu trữ tới 4000 ký tự của bất kỳ bộ ký tự nào. Việc này có thể thực hiện được không? Nếu vậy, làm thế nào?
Chúng tôi đã thử chuyển đổi Chuỗi thành UTF8
bằng cách sử dụng ByteBuffer
mà không thành công. OraclePreparedStatement.setFormOfUse(...)
cũng không giúp chúng tôi.
Chuyển sang một số CLOB
không phải là một tùy chọn. Nếu chuỗi quá dài cần phải cắt.
Đây là mã của chúng tôi tại thời điểm này:
public static void main(String[] args) throws Exception {
String ip ="193.53.40.229";
int port = 1521;
String sid = "ora11";
String username = "obasi";
String password = "********";
String driver = "oracle.jdbc.driver.OracleDriver";
String url = "jdbc:oracle:thin:@" + ip + ":" + port + ":" + sid;
Class.forName(driver);
String shortData = "";
String longData = "";
String data;
for (int i = 0; i < 5; i++)
shortData += "é";
for (int i = 0; i < 4000; i++)
longData += "é";
Connection conn = DriverManager.getConnection(url, username, password);
PreparedStatement stat = null;
try {
stat = conn.prepareStatement("insert into test_table_short values (?)");
data = shortData.substring(0, Math.min(5, shortData.length()));
stat.setString(1, data);
stat.execute();
stat = conn.prepareStatement("insert into test_table_long values (?)");
data = longData.substring(0, Math.min(4000, longData.length()));
stat.setString(1, data);
stat.execute();
} finally {
try {
stat.close();
} catch (Exception ex){}
}
}
Đây là kịch bản tạo của bảng đơn giản:
CREATE TABLE test_table_short (
DATA VARCHAR2(5 CHAR);
);
CREATE TABLE test_table_long (
DATA VARCHAR2(4000 CHAR);
);
Các trường hợp kiểm tra hoạt động hoàn hảo trên các dữ liệu ngắn. Trên dữ liệu dài tuy nhiên nó vẫn nhận được lỗi. Ngay cả khi longData
của chúng tôi chỉ dài 3000 ký tự, nó vẫn không thực thi thành công.
Cảm ơn trước!
Cảm ơn câu trả lời của bạn. Đáng buồn thay, trong trường hợp này, việc sử dụng clob là câu hỏi cho chúng tôi. Theo [link] (https://forums.oracle.com/forums/thread.jspa?threadID=2369974) đây là câu trả lời đúng. Tuy nhiên, [link] (http://stackoverflow.com/questions/81448/difference-between-byte-and-char-in-column-datatypes) là khá sai lầm trong sự phản đối khiêm tốn của tôi. Bạn có biết điều này được giải thích trong tài liệu này không? Chúng tôi đã tìm kiếm rất nhiều, nhưng không thể tìm thấy điều này. – Arolition
@Arolition - Tôi đã thêm nhận xét vào chuỗi SO. Câu trả lời là chính xác cho đến nay khi nó đi. Nó chỉ không lưu ý rằng nếu một 4000 ký tự đặc biệt đòi hỏi nhiều hơn 4000 byte dung lượng lưu trữ thì giới hạn dung lượng 4000 byte vẫn được khởi động. –
UTF-8 là mã hóa độ dài biến đổi. Nhiều ký tự Châu á yêu cầu ít nhất ba byte để mã hóa. –