yeg
2026-09-16 e617e479055d37e7482621d46dfa8608ddb55f07
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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 &lt;jdbc-url&gt; &lt;file.sql&gt;
 */
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;
    }
}