在 Microsoft SQL Server 2017 上执行长 SQL 脚本

Posted

技术标签:

【中文标题】在 Microsoft SQL Server 2017 上执行长 SQL 脚本【英文标题】:Executing a long SQL script on Microsoft SQL Server 2017 【发布时间】:2018-09-03 13:59:18 【问题描述】:

我需要通过 Java 应用程序在 Microsoft SQL Server 2017 的新实例上执行带有 DDL 和 DML 命令的 SQL 脚本(约 5000 行),该应用程序已经部署和配置了连接池和数据源。

寻找解决方案我发现的唯一方法是将脚本加载到缓冲区中,读取它,然后将每一行分成一个语​​句,然后将这些语句中的每一个单独发送到数据库实例,就像在this example 中一样。

有没有更优雅或更简单的方法来做到这一点?

【问题讨论】:

无法保证 SQL 脚本可以逐行运行 - 例如,它可能会声明变量。脚本是否包含 GO 语句? GO 语句之间的每一段代码都作为自己的实体运行,因此您可以将它们分解。 @Cato 是的,我验证了脚本并且每个命令/查询都以 GO 语句结束。那么缓冲 GO 语句之间每一行的解析器方法可能会起作用吗? 在GO之间发送每个部分,GO省略 您可能不需要编写自己的解析器。例如,您可以使用 SqlTool 中的 SqlFile 对象,如 this answer 中所示。 【参考方案1】:

在研究解决方案后,我得出结论,我的第一种方法最适合这种特定情况。基本上,我实现了一个工厂类,它为正在使用的数据库实例化了一个解析器类。

此解析器从 SQL 脚本中读取每一行并将其加载到缓冲区中,评估它是注释还是正确的行,将其添加到列表中,清除空行,然后最终在两个 GO 语句之间构建每个命令通过附加这些行并将它们传递到另一个列表,该列表将在最后返回。

package parsing;

import java.io.*
import java.util.*

public class ScriptParser implements Parser 

private static ArrayList<String> listOfQueries = null;

@Override
public ArrayList<String> createQueries(String path) 
    String queryLine = new String();
    StringBuilder sBuffer = new StringBuilder();
    listOfQueries = new ArrayList<>();
    List<String> dirtyQueries = new ArrayList<>();

    try 
        FileReader fr = new FileReader(new File(path));
        BufferedReader br = new BufferedReader(fr);
        while ((queryLine = br.readLine()) != null) 
            if (queryLine.contains("--") || queryLine.contains("/*")) 
                queryLine = "";
                dirtyQueries.add(queryLine);
             else 
                dirtyQueries.add(queryLine + " ");
            
        
        br.close();
        for (Iterator<String> iter = dirtyQueries.listIterator(); iter.hasNext();) 
            //TODO
            String str = iter.next();
            if (str.isEmpty() || str.trim().isEmpty()) 
                iter.remove();
             else 
                //DO NOTHING
            
        

        StringBuilder queryStatement = new StringBuilder();
        for (int i = 0; i < dirtyQueries.size(); i++) 
            //TODO
            if (!dirtyQueries.get(i).contains("GO") || !dirtyQueries.get(i).contains("GO ")) 
                queryStatement.append(dirtyQueries.get(i)).append(" ");
             else 
                listOfQueries.add(queryStatement.toString());
                queryStatement = new StringBuilder();
            
        
     catch (Exception e) 
        e.printStackTrace();
        System.out.println(sBuffer.toString());
    
    return listOfQueries;
  
    

然后,列表中的每个条目都被循环并传递给Statement 并单独执行。

【讨论】:

以上是关于在 Microsoft SQL Server 2017 上执行长 SQL 脚本的主要内容,如果未能解决你的问题,请参考以下文章

客户端统计表 (Microsoft SQL Server Management Studio)

Microsoft SQL Server 2016,T-SQL:根据各个日期获取数据集的日期范围

P6 Professional Installation and Configuration Guide (Microsoft SQL Server Database) 16 R1

SQLSTATE[08001]:[Microsoft][ODBC Driver 17 for SQL Server]TCP 提供程序:错误代码 0x2746

如何把SQL Server 2008卸载干净

Microsoft][ODBC SQL Server Driver][DBNETLIB]SQL Server不存在或访问被拒绝