2009-10-05 5 views
0

Oracle 데이터베이스에서 데이터를 가져 오는 Java 준비 문과 함께 작업하고 있습니다. 일부 성능 문제로 인해 쿼리는 "가상 열"을 인덱스로 사용합니다.준비된 문 - where 절의 일부로 함수 사용

쿼리는 다음과 같습니다 :이 작동하지 않습니다

String status = "processed"; 
String customerId = 123; 
String query = "SELECT DISTINCT trans_id FROM trans WHERE status = " + status + " AND FN_GET_CUST_ID(trans.trans_id) = " + customerId; 

Connection conn = getConnection(); 
PreparedStatement ps = null; 
ResultSet rs = null; 

try { 
    ps = conn.prepareStatement(query); 
    ps.execute(); 
    ... 
} catch (...) 

. where 절의 일부로 함수를 사용하면 SQLException이 발생합니다. 나는 CallableStatement에 대해 알고 있으며, 먼저 그것을 사용할 수 있고 그 결과를 연결시킬 수 있다는 것을 알고있다. 그러나이 테이블은 인덱스의 일부로 FN_GET_CUST_ID (trans_id)를 사용합니다. 쿼리 매개 변수로 데이터베이스 함수와 함께 준비된 문을 사용하는 방법이 있습니까?

+1

처리 된 상태를 인용 부호로 묶어야합니다. 예외의 원인이 그 때문일까요? – quosoo

+0

WHERE 절에 함수가 있어야만 문제가 발생할 수 있습니다. 오류 코드 및 메시지 (SQLException.getErrorCode)를 게시 할 수 있습니까? 쿼리가 실제로 SQL * Plus에서 작동합니까? –

+0

죄송합니다. 게시 한 예가 그대로 복사되지 않았습니다. 나는 과도한 비 필수적인 것들을 많이 제거하기 위해 그것을 다듬 으려고 노력했다. 누락 된 따옴표는 문제가 아닙니다. – emulcahy

답변

6
  1. SQL에 대한 인수를 문자열로 연결하지 마십시오. 항상 자리 표시 자 (?)와 setXxx(column, value);을 사용하십시오.

  2. 좋아하는 DB 도구에서 SQL을 실행하면 동일한 오류가 발생합니다. 문제는 오라클이 어떤 이유로이 기능을 사용할 수 없다는 것입니다. 어떤 오류 코드가 나옵니까?

+2

+1 자리 표시 자 – Powerlord

+1

문제는 함수에 공용 실행 권한이 없었습니다. # 2 Aaron의 코멘트 "문제는 오라클이 어떤 이유로이 기능을 사용할 수 없다는 것입니다." 궁극적으로 내가 문제를 발견하도록 이끌어 주었고, 그래서 그에게 신용을 주었다. – emulcahy

0

언뜻보기에 쿼리가 잘못된 것 같습니다. 앞뒤에 status 변수를 사용하기 전과 후에 아포스트로피가 누락되었습니다 (상태가 varchar 열인 것으로 가정).

String query = "SELECT DISTINCT trans_id FROM trans 
WHERE status = '" + status + "' AND FN_GET_CUST_ID(trans.trans_id) = " + customerId; 

편집 : 자바 배경이 아닙니다. 그러나 @Aron이 말했듯이 자리 표시 자 &을 사용하는 경우 어떤 방법을 사용하여 매개 변수의 값을 설정하여 SQL Injection을 피할 수 있습니다.

+0

질문에 대한 첫 번째 의견에서 지적했듯이 맞습니다. 아마 Aaron이 언급 한 쿼리에서 자리 표시자를 사용하는 것이 더 낫습니다. 그렇지 않으면 PreparedStatement에서 아무런 이점이 없습니다. – quosoo

1

고객 ID가 숫자 인 경우 String이 아닌 int로 유지하십시오.

String query = "SELECT DISTINCT trans_id FROM trans WHERE status = ? AND FN_GET_CUST_ID(trans.trans_id) = ?"; 

ps = conn.prepareStatement(query); 
ps.setString(1, status); 
ps.setInt(2, customerId); 
ps.execute(); 

준비된 문장의 다른 장점 외에도 당신은 문자열 인용에 대해 기억할 필요가 없습니다 (이 가장 가능성이 오류가 발생합니다) 및 특수 문자의 이스케이프 : 그런 다음 다음을 수행하십시오.