【发布时间】:2015-03-21 00:07:15
【问题描述】:
我有一个 sql 脚本文件,我需要通过 java 执行其中的命令。我在互联网上搜索了同样的内容,我得到了一些定义解析器的代码来拆分 SQL 语句并执行它。但是它们都不适用于我的 sql 脚本文件。因为我的脚本文件同时包含 create 语句和结尾没有分号的 alter 语句[相反它有 GO]任何人都可以提出执行脚本文件的解决方案吗? 谢谢, 马赫什
【问题讨论】:
我有一个 sql 脚本文件,我需要通过 java 执行其中的命令。我在互联网上搜索了同样的内容,我得到了一些定义解析器的代码来拆分 SQL 语句并执行它。但是它们都不适用于我的 sql 脚本文件。因为我的脚本文件同时包含 create 语句和结尾没有分号的 alter 语句[相反它有 GO]任何人都可以提出执行脚本文件的解决方案吗? 谢谢, 马赫什
【问题讨论】:
对于简单的脚本,我通常使用来自 ibatis 的这个类 - ScriptRunner。或者,您可以从 Java 生成一个新的数据库客户端进程并输入您不想执行的脚本。这适用于所有脚本,因为 ScriptRunner 之类的简单解决方案在 sql 文件中的分隔符发生更改时无法正常工作。
这是一个如何将 sql 作为字符串提供给生成的 db 客户端进程的示例:
private void runSql(String pSql) {
String tCommand = "mysql -u " + username + (password != null ? " -p" + password : "") + " " + dbName;
System.out.println(tCommand);
try {
Process tProcess = Runtime.getRuntime().exec(tCommand);
OutputStream tOutputStream = tProcess.getOutputStream();
Writer w = new OutputStreamWriter(tOutputStream);
System.out.println(pSql);
w.write(pSql);
w.flush();
Scanner in = new Scanner(tProcess.getErrorStream());
String errorMessage = "";
while (in.hasNext()) {
errorMessage += in.next() + " ";
}
if (errorMessage.length() > 0) {
System.out.println(errorMessage);
throw new ClientSqlExecutionException(errorMessage);
}
} catch (IOException e) {
e.printStackTrace();
}
}
【讨论】:
看看 Mybatis Migrations 代码,它做了一些你需要的事情:
【讨论】:
您需要更改解析器,使其生成可执行语句。但我不确定我是否理解您所说的“通过 Java 执行”的意思。
Java 不会执行那些 SQL 语句 - 您连接的数据库会执行。 Java 可以使用 JDBC 连接到数据库并从文件中发送 SQL 语句。
我不明白为什么必须解析 SQL,除非您希望 Java 在将它们发送到数据库服务器之前对其进行验证。服务器将再次解析和验证它们,所以感觉就像你在白白做额外的工作。
【讨论】:
假设我理解您的问题,我可以向您提出的最简单的解决方案就是这个。
1) 通过 Java IO 将文本文件读入字符串或数组。 2) 通过 JDBC 将字符串或数组传递给 MySQL。
从文件中读取示例,
import java.io.*;
class FileRead
{
public static void main(String args[])
{
try{
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream("textfile.txt");
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
//Read File Line By Line
while ((strLine = br.readLine()) != null) {
// Print the content on the console
System.out.println (strLine);
}
//Close the input stream
in.close();
}catch (Exception e){//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
}
}
从http://www.roseindia.net/java/beginners/java-read-file-line-by-line.shtml获得
【讨论】:
最简单的方法是简单地获取语句并检查它们是否需要它们在末尾的半列:(这是一个示例,仅当它是逐行语句时才有效:
public void executeScript(String script) {
BufferedReader in = new BufferedReader(new FileReader(script));
while (in.read() > 0) {
String statement = in.readLine();
statement = statement.trim().toLowerCase();
String command = statement.split("[ ]+")[0]; // split the statement.
if (command.equals("insert") || command.equals("update") /* || any other */) {
statement = statement + ";";
}
// execute statement using jdbc
}
}
如果你不知道如何使用 jdbc,请问:-)
【讨论】:
使用这个完全自包含的slightly modified version of the com.ibatis.common.jdbc.ScriptRunner class,即您不需要任何第三方 jar 依赖项。
可以将分隔符从; 更改为GO。我认为这应该可以解决问题。
这是一个例子:
Reader reader = new BufferedReader(*** Your FileReader instance ***);
try
{
ScriptRunner runner = new ScriptRunner(connection, false, true);
runner.setDelimiter("GO", true);
runner.runScript(reader);
}
finally
{
reader.close();
}
【讨论】:
Apache Ant SQL 任务为我工作。 https://ant.apache.org/manual/Tasks/sql.html
【讨论】: