我希望这次能收到我的答案
我写了下面的代码,但不知道我的错误在哪里我认为似乎是正确的
这段代码应该在oraclexe中插入超过一百万条记录我在逐个执行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*./»«،~!@#$%^&()_-"+=:;|<>?“؟”’{}[]‘,\tnrfabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ...—`—ـ؛–…_");
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();
}
}
您似乎试图通过传递多组值,用单个insert
语句插入多行;st
最终显示为:
insert into tokens5(token,tokenlength) values (?,?), (?,?);(?,?), ...;`
具有数千个值对占位符。不能像那样传递多组值。Oracle不希望第一个(?,?)
后面有逗号,因此出现了ORA-00933错误。在i
while循环中,每次都要放一个分号,因此其中还有多个分号。正如Mark Rotteveel所指出的,您不应该有任何语句,因为Oracle JDBC不允许多个语句。
您最好将字符串标记器实现为数据库上的一个函数,然后执行单个insert ... select from newstext
,而不是提取所有数据,转换为并将其推回。不过,你至少应该批量更新。例如,可以将tokens
作为数组参数传递给存储过程。
不过,我很难理解你到底在做什么,因为看起来你几乎在任何字符上分割一个字符串,这不会给实际的键留下太多,是吗?虽然很难理解。。。
如果查看《SQL语言参考》中的Oracle INSERT描述,您可以看到Oracle不支持使用VALUES
插入多行。正如我在上面评论的那样,在查询中使用;
并不总是有效的,因为它通常不是查询本身的一部分,而是命令行或脚本输入的终止符。
在您的具体情况下,您甚至试图将多个语句放在一个prepare中。在JDBC中,单个语句prepare(或execute)应该只有一个实际的语句,而不是由;
分隔的多个语句。驱动程序(或数据库)通常不允许这样做,尽管有些驱动程序提供了执行多条语句的选项,但这与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。