2010-05-18 134 views
26

Mã truy vấn và truy vấn:Không thể sử dụng truy vấn LIKE trong JDBC PreparedStatement?

ps = conn.prepareStatement("select instance_id, ? from eam_measurement where resource_id in (select RESOURCE_ID from eam_res_grp_res_map where resource_group_id = ?) and DSN like '?' order by 2"); 
ps.setString(1,"SUBSTR(DSN,27,16)"); 
ps.setInt(2,defaultWasGroup); 
ps.setString(3,"%Module=jvmRuntimeModule:freeMemory%"); 
rs = ps.executeQuery(); 
while (rs.next()) { bla blah blah blah ... 

Trả về một sản phẩm nào ResultSet.

Qua gỡ lỗi cơ bản tôi đã tìm thấy các ràng buộc thứ ba đó là vấn đề tức là

DSN like '?' 

Tôi đã thử tất cả các loại biến thể, hợp lý nhất trong số đó dường như được sử dụng:

DSN like concat('%',?,'%') 

nhưng điều đó không hoạt động vì tôi thiếu số ' ở hai bên của chuỗi được ghép vào nhau để tôi thử:

DSN like ' concat('%',Module=P_STAG_JDBC01:poolSize,'%') ' order by 2 

nhưng tôi dường như không thể tìm cách để có được chúng trong các tác phẩm đó.

Tôi đang thiếu gì?

+0

Viết mã Java trong tệp JSP thay vì trong một lớp Java thực (nơi bạn ** nên ** đã thực hiện) và gặp sự cố mã Java cụ thể không làm cho nó trở thành một vấn đề JSP. Bạn sẽ phải đối mặt chính xác cùng một vấn đề khi làm như vậy trong một lớp Java thực sự. Vì vậy, tôi đã xóa thẻ '[jsp]' vì nó không liên quan. – BalusC

+1

True nó không phải là JSP cụ thể, nhưng sau đó không có gì * sai * với việc sử dụng mã như vậy trong một servlet theo hầu hết các sách tôi đã đọc, đặc biệt khi nó là một trang báo cáo siêu đơn giản của ít hơn 40 dòng mã. là một chút quá mức cần thiết :) Nhưng tôi đánh giá cao quan điểm của bạn! – SeerUK

Trả lời

52

Đầu tiên, giữ chỗ PreparedStatement (những điều ?) chỉ dành cho giá trị cột chỉ, không cho tên bảng, tên cột, hàm/mệnh đề SQL, v.v. Thay vào đó hãy sử dụng tốt hơn String#format(). Thứ hai, bạn nên không phải báo giá trình giữ chỗ như '?', nó sẽ chỉ làm sai truy vấn cuối cùng. Người đặt mã số PreparedStatement đã thực hiện công việc trích dẫn (và thoát) cho bạn.

Đây là SQL cố định:

private static final String SQL = "select instance_id, %s from eam_measurement" 
    + " where resource_id in (select RESOURCE_ID from eam_res_grp_res_map where" 
    + " resource_group_id = ?) and DSN like ? order by 2"); 

Dưới đây là làm thế nào để sử dụng nó:

String sql = String.format(SQL, "SUBSTR(DSN,27,16)"); // This replaces the %s. 
preparedStatement = connection.prepareStatement(sql); 
preparedStatement.setInt(1, defaultWasGroup); 
preparedStatement.setString(2, "%Module=jvmRuntimeModule:freeMemory%"); 

Xem thêm:

2

Bỏ qua số ' xung quanh ?. Không có ', ? là trình giữ chỗ cho thông số. Với nó, đó là một chuỗi SQL (tức là giống như "?" trong Java).

Sau đó, bạn phải nối chuỗi ở phía Java; bạn không thể chuyển các hàm SQL làm tham số cho các truy vấn; chỉ các giá trị cơ bản (như chuỗi, số nguyên, vv) vì trình điều khiển JDBC sẽ chuyển đổi tham số thành kiểu SQL mà cơ sở dữ liệu mong đợi và nó không thể thực hiện các hàm SQL trong bước này.

+0

Nếu không có '' xung quanh? Tôi cũng nhận được một tập kết quả rỗng. Không ngạc nhiên khi tôi đoán như sau đó sql sẽ đọc: và DSN như% Module = P_STAG_JDBC01: poolSize% mà oracle không thích và trả lời với: Thiếu tham số IN hoặc OUT tại index :: 1 (error code = 17041) Vì vậy tôi cần thêm '' s để ràng buộc khi tôi đặt nó thông qua ps.setString? – SeerUK

+0

ví dụ: ps.setString (3, "'Module = jvmRuntimeModule: freeMemory'"); Nhưng cũng cung cấp một tập kết quả trống, cũng như ps.setString (3, "\ 'Module = jvmRuntimeModule: freeMemory \'"); Mặc dù tài liệu java nói rằng không cần thiết phải thoát khỏi một "bên trong" " – SeerUK

+0

@SeerUK: Thông báo lỗi đến từ tham số 1, không phải từ tham số 3! –

10

Có hai vấn đề với tuyên bố của bạn. Bạn phải hiểu cách các biến liên kết hoạt động. Truy vấn là không được xử lý bằng cách thay thế các ký tự ? với thông số của bạn. Thay vào đó, câu lệnh được biên dịch với phần giữ chỗ và sau đó, trong khi thực hiện, các giá trị thực tế của các tham số được cung cấp cho DB.

Nói cách khác, bạn phân tích các truy vấn sau đây:

SELECT instance_id, :p1 
    FROM eam_measurement 
WHERE resource_id IN (SELECT RESOURCE_ID 
         FROM eam_res_grp_res_map 
         WHERE resource_group_id = :p2) 
    AND DSN LIKE '?' 
ORDER BY 2 

Tôi khá chắc chắn rằng các tham số cuối cùng sẽ bị bỏ qua vì nó là trong một chuỗi ký tự phân cách. Ngay cả khi nó không bị bỏ qua, nó không có ý nghĩa để có ' ký tự xung quanh bởi vì Oracle sẽ không ràng buộc một tham số trong một chuỗi (Tôi ngạc nhiên khi nó không đưa ra bất kỳ lỗi nào, bạn có bắt được ngoại lệ không?).

Bây giờ, nếu bạn thay thế DNS LIKE '?' bằng DSN LIKE ? và ràng buộc "%Module=jvmRuntimeModule:freeMemory%", điều này sẽ có ý nghĩa và phải trả về đúng hàng.

Bạn vẫn có vấn đề với tham số đầu tiên của bạn, nó sẽ không làm những gì bạn mong đợi, tức là truy vấn sẽ được thực thi sẽ tương đương với truy vấn sau đây:

SELECT instance_id, 'SUBSTR(DSN,27,16)' 
    FROM ... 

mà không phải là ở tất cả giống như

SELECT instance_id, SUBSTR(DSN,27,16) 
    FROM ... 

tôi sẽ đề nghị phân tích cú pháp (= prepareStatement) truy vấn sau đây nếu bạn mong đợi SUBSTR phải năng động:

SELECT instance_id, SUBSTR(DSN,?,?) 
    FROM eam_measurement 
WHERE resource_id IN (SELECT RESOURCE_ID 
         FROM eam_res_grp_res_map 
         WHERE resource_group_id = ?) 
    AND DSN LIKE ? 
ORDER BY 2 
0

Bạn có thể thử:

String beforeAndAfter = "%" + yourVariable + "%"; 
11

Nếu bạn muốn sử dụng như thế nào trong tuyên bố chuẩn bị và cũng muốn sử dụng% nhân vật trong NHƯ;

viết tuyên bố chuẩn bị như bình thường ".... như thế nào? ...." và trong khi gán giá trị tham số để đặt câu hỏi đánh dấu sử dụng

ps.setString(1, "%" + "your string value" + "%");

này sẽ làm việc :)

0

này nên công việc:

"\'" + "?" + "\'" 
0
PreparedStatement ps = con.prepareStatement(
    "select columname from tablename where LOWER(columnname) LIKE LOWER('"+var+"%')"); 

đây var là biến trong đó giá trị được tìm kiếm được lưu trữ ...

+1

Vui lòng giải thích thêm một chút và định dạng mã của bạn (bạn có thể sử dụng "dấu tích sau" hoặc thụt lề 4 khoảng trắng). [Cách trả lời] (http://stackoverflow.com/help/how-to-answer) – AgataB

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