import java.nio.charset.StandardCharsets;
|
import java.nio.file.Files;
|
import java.nio.file.Path;
|
import java.sql.Connection;
|
import java.sql.DriverManager;
|
import java.sql.Statement;
|
import java.util.ArrayList;
|
import java.util.List;
|
|
/**
|
* 把一个 .sql 文件按语句逐条执行(备份文件与一次性 DDL 用)。
|
*
|
* <p>不处理 DELIMITER:Flyway 自己的迁移文件由 Flyway 执行,这里只跑不含存储过程的脚本。
|
* 用法:java RunSqlFile <jdbc-url> <file.sql>
|
*/
|
public class RunSqlFile {
|
|
public static void main(String[] args) throws Exception {
|
String url = args[0];
|
Path file = Path.of(args[1]);
|
List<String> statements = split(Files.readString(file, StandardCharsets.UTF_8));
|
int failed = 0;
|
try (Connection connection = DriverManager.getConnection(url, "root", "123456")) {
|
try (Statement statement = connection.createStatement()) {
|
for (String sql : statements) {
|
try {
|
statement.execute(sql);
|
} catch (Exception exception) {
|
failed++;
|
String head = sql.length() > 120 ? sql.substring(0, 120) + "..." : sql;
|
System.out.println("!! 失败:" + exception.getMessage());
|
System.out.println(" " + head.replace('\n', ' '));
|
}
|
}
|
}
|
}
|
System.out.println("执行语句 " + statements.size() + " 条,失败 " + failed + " 条");
|
}
|
|
/** 按行尾分号切分,并支持 {@code DELIMITER} 指令(迁移里的存储过程需要)。跳过空语句与纯注释块。 */
|
private static List<String> split(String content) {
|
List<String> statements = new ArrayList<>();
|
StringBuilder current = new StringBuilder();
|
String delimiter = ";";
|
for (String line : content.split("\n")) {
|
String trimmed = line.trim();
|
String upper = trimmed.toUpperCase(java.util.Locale.ROOT);
|
if (upper.startsWith("DELIMITER ")) {
|
delimiter = trimmed.substring("DELIMITER ".length()).trim();
|
continue;
|
}
|
if (trimmed.startsWith("--") && current.toString().isBlank()) continue;
|
current.append(line).append('\n');
|
if (trimmed.endsWith(delimiter)) {
|
String sql = current.toString().trim();
|
String withoutTrailing = sql.substring(0, sql.length() - delimiter.length()).trim();
|
if (!withoutTrailing.isBlank() && !withoutTrailing.startsWith("--")) statements.add(withoutTrailing);
|
current.setLength(0);
|
}
|
}
|
return statements;
|
}
|
}
|