2009-03-02 28 views
7

Tôi có một truy vấn mà cóOracle10 và JDBC: làm thế nào để làm cho CHAR bỏ qua dấu cách không gian so sánh?

... WHERE PRT_STATUS = 'ONT' ...

Trường prt_status được định nghĩa là CHAR (5) mặc dù. Vì vậy, nó luôn luôn đệm với không gian. Truy vấn không khớp với kết quả. Để thực hiện việc truy vấn này tôi phải làm

... WHERE rtrim (PRT_STATUS) = 'ONT'

mà không làm việc.

Điều đó thật khó chịu.

Đồng thời, một vài máy khách DBMS thuần-Java (Oracle SQLDeveloper và AquaStudio) Tôi KHÔNG có vấn đề với truy vấn đầu tiên, chúng trả lại kết quả chính xác. TOAD cũng không có vấn đề gì.

Tôi cho rằng họ chỉ cần đặt kết nối vào một số chế độ tương thích (ví dụ ANSI), do đó, Oracle biết rằng CHAR (5) được mong đợi sẽ được so sánh không liên quan đến ký tự dấu.

Tôi làm cách nào với các đối tượng Kết nối mà tôi nhận được trong ứng dụng của mình?

CẬP NHẬT Tôi không thể thay đổi lược đồ cơ sở dữ liệu.

GIẢI PHÁP Đó thực sự là cách Oracle so sánh các trường có thông số.

Khi liên kết được thực hiện, chuỗi được chuyển qua PreparedStatement.setString(), đặt loại thành VARCHAR, và do đó Oracle sử dụng so sánh không được đệm - và không thành công.

Tôi đã cố gắng sử dụng setObject (n, str, Types.CHAR). Không. Decompilation cho thấy rằng Oracle bỏ qua CHAR và chuyển nó vào như một VARCHAR một lần nữa.

Các biến thể mà cuối cùng làm việc là

setObject(n,str,OracleTypes.FIXED_CHAR); 

Nó làm cho mã không cầm tay mặc dù.

Khách hàng UI thành công vì một lý do khác - họ sử dụng ký tự chữ cái, không ràng buộc. Khi tôi gõ PRT_STATUS = 'ONT', 'ONT' là một chữ, và như vậy so với cách sử dụng độn.

Trả lời

8

Lưu ý rằng Oracle compares CHAR values using blank-padded comparison semantics.

Từ Datatype Comparison Rules,

Oracle sử dụng so sánh trống độn ngữ nghĩa chỉ khi cả hai giá trị trong việc so sánh là một trong hai biểu thức của datatype CHAR, NCHAR, chèn thêm các chữ, hoặc các giá trị được trả về bởi hàm USER .

Trong ví dụ của bạn, được 'ONT' chuyển thành tham số liên kết hoặc được tích hợp vào truy vấn theo văn bản, như bạn đã minh họa? Nếu tham số liên kết, hãy đảm bảo rằng thông số đó bị ràng buộc là loại CHAR. Nếu không, hãy xác minh phiên bản thư viện máy khách được sử dụng, vì các phiên bản Oracle cũ thực sự (ví dụ: v6) sẽ có ngữ nghĩa so sánh khác nhau cho CHAR.

+0

Tốt thôi. Xem câu trả lời cập nhật của tôi sau đó. – vladr

+0

Hmm ... có ý nghĩa. SetString của JDBC sử dụng VARCHAR để ràng buộc một tham số chuỗi. Không chắc liệu tôi có thể sử dụng điều này để giải quyết vấn đề, nhưng ít nhất nó trở nên rõ ràng hơn bây giờ. –

+0

Bạn có thể đúng: "Oracle sử dụng ngữ nghĩa so sánh không được đệm khi một hoặc cả hai giá trị trong so sánh có kiểu dữ liệu VARCHAR2 hoặc NVARCHAR2". Tôi cần làm một bài kiểm tra để kiểm tra nó. –

0

Tôi sẽ thay đổi CHAR (5) cột thành varchar2 (5) trong db.

+0

Out of câu hỏi. DB không thuộc về nhóm của chúng tôi. –

1

Nếu bạn không thể thay đổi bảng cơ sở dữ liệu, bạn có thể sửa đổi truy vấn của mình.

Một số lựa chọn thay thế cho RTRIM:

.. ĐÂU PRT_STATUS như 'ONT%' ...

.. ĐÂU PRT_STATUS = 'ONT' ... - 2 không gian màu trắng đằng sau T

.. ĐÂU PRT_STATUS = RPAD ('ONT', 5,' ') ...

0

bạn có thể sử dụng dàn diễn viên đến hoạt động char trong truy vấn của bạn:

... WHERE PRT_STATUS=cast('ONT' as char(5)) 

Hoặc trong nhiều cách JDBC generic:

... WHERE PRT_STATUS=cast(? as char(5)) 

Và sau đó trong mã JDBC của bạn không sử dụng statement.setString(1, "ONT");

Các vấn đề liên quan