sql命令没有正确结束(我的错误在哪里)

时间:2013-07-23 18:46:36

标签: java jdbc insert oracle-xe ora-00933

我希望这次能得到答案

我写下面的代码,但不知道我的错误在哪里 这似乎是正确的我认为

此代码应在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]," 0123456789*./»«،~!@#$%^&()_-\"+=:;|<>?“؟”’{}[]‘,\\\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();
}









}

2 个答案:

答案 0 :(得分:1)

您似乎尝试通过传递多组值来尝试使用单个insert语句插入多行; st似乎最终成为:

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

有数千个值对占位符。您不能传递多组这样的值。 Oracle在第一个(?,?)之后不期待逗号,因此ORA-00933错误。当你在i while循环中每次放置一个分号时,你还有多个分号。正如Mark Rotteveel指出的那样,你不应该有任何东西,因为Oracle JDBC不允许多个语句。

您可能最好将字符串标记生成器作为数据库上的函数实现,然后执行单个insert ... select from newstext,而不是将所有数据拉出,转换为并将其推回。您应该至少批量更新您的更新。例如,您可以将tokens作为数组参数传递给存储过程。

我很难理解你真正在做什么,因为看起来你在几乎所有角色上都分裂了一个字符串,这对于实际的密钥来说并没有多大帮助,是吗?虽然很难遵循......

答案 1 :(得分:1)

如果查看SQL语言参考中的Oracle INSERT description,则可以看到Oracle不支持使用VALUES插入多行。同样如上所述,在查询中使用;并不总是有效,因为它通常不是查询本身的一部分,而是命令行或脚本输入的终止符。

在您的具体情况下,您甚至尝试将多个语句放入一个准备中。在JDBC中,单个语句准备(或执行)应该只是一个实际语句,而不是由;分隔的多个语句。驱动程序(或数据库)通常不允许它,尽管有些提供了执行多个语句的选项,但这与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();
}

根据数据库+驱动程序的不同,这将具有与多值插入相似的运行时性能(我相信它与Oracle一样),或者只是表现得就像使用不同的值多次执行一个PreparedStatement一样。