2013-07-23 4 views
0

내가 내 대답SQL 명령은

내가 코드를 아래에 쓴이 시간을받을 희망하지만, 내 실수 이다 올바른지 내가

이 코드를 생각하는 것 같다 모른다 (여기서 내 실수이다) 백만 분의 레코드를 oracle xe에 삽입해야합니다 PreparedStatement를 하나씩 실행하면 하나의 insert 문으로 작성했습니다 하지만 실행 시간은 6 시간 !!!!!! 내가 강제 되었기 때문에 사용에 Thread.sleep()

package tokenizing; 
import java.sql.*; 
import java.util.StringTokenizer; 

public class TokenExtraction2 { 


    public static void main(String[] args) throws Exception { 
     String myText[]=new String[2276]; 
     Jdbc db=new Jdbc(); 
     String st1=null; 
     int i=0; 
     int j=0; 
     String tokens[][]=new String [3000000][2]; 
     st1="select ntext from NEWSTEXT "; 
     ResultSet result=db.select(st1); 
     while(result.next()) 
     { 
      myText[i]=result.getString("ntext"); 
      ++i; 
     } 
     db.closedb(); 
     i=0; 
     StringBuilder st= new StringBuilder("insert into tokens5(token,tokenlength) values"); 
     while(i<2276) 
     { 

      StringTokenizer s=new StringTokenizer(myText[i],"*./»«،[email protected]#$%^&()_-\"+=:;|<>?“؟”’{}[]‘,\\\t\n\r\fabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ...—`—ـ؛–…_"); 
      while(s.hasMoreTokens()){ 
       String key=s.nextToken(); 
       tokens[j][0]=key; 
       tokens[j][1]=(key.length())+""; 
       st.append("(?,?)"); 
       if(i<2276 && s.hasMoreTokens()) 
       st.append(", "); 
       else 
       st.append(";"); 
       //db.insert(st, key, key.length()); 
       //db.closedb(); 
       System.out.println(key+"\t"); 



        j++; 
      } 
      System.out.println("num of news is: "+i); 
      System.out.println("*****************************************************************************************"); 
      System.out.println("num of tokens is: "+j); 
      System.out.println("next news"+"\t"); 
      //j=0; 

      i++; 
     } 

     System.out.println(st); 
     int k=0; 

     Class.forName("oracle.jdbc.driver.OracleDriver") ; 
     Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe","ALBALOO","myjava123"); 
     PreparedStatement ps=con.prepareStatement(st.toString()); 
    // con.setAutoCommit(false); 
     //j=1; 
     i=0; 
     //j=j-286; 
     while(k<j) 
     { 

      i=i+1; 

       ps.setString(i, tokens[k][0]); 

      System.out.println(i); 
       i=i+1; 
       ps.setInt(i,Integer.parseInt(tokens[k][1])); 

       System.out.println(k+2); 

       k++; 


     } 

     ps.executeUpdate(); 
    //con.commit(); 
} 









} 

답변

1

당신은 여러 값 세트를 전달하여, 하나의 insert 문으로 여러 행을 삽입하려고 것 같다; 값 쌍 자리의 수천

insert into tokens5(token,tokenlength) values (?,?), (?,?);(?,?), ...;` 

: st는로 끝날 것으로 보인다. 그런 값의 여러 세트를 전달할 수 없습니다. 오라클은 첫 번째 (?,?) 이후에 쉼표가 필요하지 않으므로 ORA-00933 오류가 발생합니다. 당신은 또한 while 루프 안에 각각주위에 하나씩 넣을 때 세미콜론을 여러 개 넣을 수 있습니다. Mark Rotteveel이 지적했듯이, Oracle JDBC는 여러 문장을 허용하지 않기 때문에 어떤 것도 가질 수 없습니다.

데이터베이스의 함수로 문자열 토크 나이저를 구현 한 다음 모든 데이터를 끌어 와서 다시 밀어 넣는 것보다는 insert ... select from newstext을 사용하는 것이 더 나을 것입니다. 적어도 업데이트를 배치해야합니다. 예를 들어 tokens을 저장 프로 시저에 대한 배열 인수로 전달할 수 있습니다.

실제 키를 많이 남기지 않는 캐릭터를 꽤 많이 쪼개는 것처럼 보이므로 실제로하고있는 것을 이해하는 데 어려움을 겪고 있습니까? ...

+0

오라클에서 여러 행을 삽입 할 수 없음을 의미합니까? 배치 문을 사용하여이 작업을 시도했지만 강제로 thread.sleep을 사용했습니다. – sara

+0

또한 ';'은 문에 포함하면 안됩니다. 세미콜론은 명령문 종결 자이며 대개의 경우 CLI 또는 스크립트 입력에만 사용됩니다. 대부분의 데이터베이스는 실제 명령문의 일부로 ';'를 지원하지 않으므로 데이터베이스 또는 JDBC 드라이버에서 오류가 발생합니다. –

+0

여러 행을 삽입하지 않고 하나의 행을 삽입합니다. 이것은 하나의'insert' 문입니다.여러 개의'(?,?)'를'values' 절의 일부로 전달해도 다중 행이되지는 않습니다. 당신이하고있는 생각을 확인하기 위해 실제'st' 결과 (또는 어쨌든 그것의 시작)를 질문에 추가 할 수 있습니까? –

1

SQL 언어 참조에서 Oracle INSERT description을 보면 오라클이 VALUES을 사용하여 여러 행을 삽입하는 것을 지원하지 않는다는 것을 알 수 있습니다. 또한 위에 언급 한대로 쿼리에서 ;을 사용하는 것이 일반적으로 쿼리 자체의 일부가 아니기 때문에 항상 작동하지는 않습니다. 명령 줄 또는 스크립트 입력에 대한 종결 자입니다.

구체적인 경우에는 하나의 준비에 여러 개의 명령문을 넣으려고합니다. JDBC에서 단일 명령문 준비 (또는 실행)는 하나의 실제 명령문이어야하며 복수 명령문은 ;으로 분리되지 않아야합니다. 드라이버 (또는 데이터베이스)는 일반적으로이를 허용하지 않지만, 일부는 여러 명령문을 실행하는 옵션을 제공하지만 JDBC와 호환되지는 않습니다. 다중 값을 삽입 할이 (내가이하는 오라클과 생각)과 유사한 런타임 성능을해야합니다

con.setAutoCommit(false); 
try (
    PreparedStatement pstmt = con. 
     prepareStatement("insert into tokens5(token,tokenlength) values (?, ?)" 
) { 
    // I use tokens as an abstraction on how you get the token and its length 
    while (tokens.next()) { 
     pstmt.setString(1, tokens.token()); 
     pstmt.setInt(2, tokens.length()); 
     pstmt.addBatch(); 
    }; 
    pstmt.executeBatch(); 
    // Optionally do something with result of executeBatch() 
    con.commit(); 
} 

데이터베이스 + 드라이버에 따라, 또는 단순히 행동 :

대신 당신은 JDBC 업데이트를 일괄 사용할 수 있습니다 하나의 PreparedStatement를 여러 값으로 여러 번 실행 한 경우

+0

오라클 xe의 배치 크기는 무엇입니까? – sara

+0

일괄 처리는 afaik입니다. 오라클은 사용자가 만든만큼 큰 크기입니다. 오라클은 [advice] (http : //docs.oracle.com/cd/E11882_01/java.112/e16548/oraperf.htm)에서 50에서 100 사이의 크기를 사용하여 드라이버의 메모리 소비를 제한하십시오 ('표준'JDBC 배치 및 특정 오라클 배치 기능은 기본적으로 사용하지 않도록 설정되어 있으며 사용하지 않는 것이 좋습니다.) 또한이 문제에 대해 걱정할 필요가 있다고 생각합니까? –

+0

예, 시간이 조금 지나면 oracle- xe (랩톱 80 요청) "ORA-12519 : TNS : 적절한 서비스 처리기를 찾을 수 없습니다." 원인 : 청취자가 클라이언트 연결에 적합한 서비스 처리기를 찾을 수 없습니다. "강제로 d는 thread.sleep을 사용합니다. – sara