执行大型SQL脚本(使用GO命令)

时间:2020-03-05 18:46:47  来源:igfitidea点击:

我需要从C程序中执行大量SQL语句集(创建一堆表,视图和存储过程)。

这些语句需要用GO语句分隔,但是SqlCommand.ExecuteNonQuery()不喜欢GO语句。我想提供参考的解决方案是在" GO"行上分割SQL字符串,并分别执行每个批处理。

有没有更简单/更好的方法?

解决方案

回答

我也遇到了同样的问题,除了将单个SQL操作拆分为单独的文件,然后依次执行所有其他操作外,我找不到其他任何方法。

显然问题不在于DML命令列表,它们之间可以在没有GO的情况下执行;使用DDL的不同故事(创建,更改,删除...)

回答

这就是我共同解决当前问题的方法。

private void ExecuteBatchNonQuery(string sql, SqlConnection conn) {
    string sqlBatch = string.Empty;
    SqlCommand cmd = new SqlCommand(string.Empty, conn);
    conn.Open();
    sql += "\nGO";   // make sure last batch is executed.
    try {
        foreach (string line in sql.Split(new string[2] { "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries)) {
            if (line.ToUpperInvariant().Trim() == "GO") {
                cmd.CommandText = sqlBatch;
                cmd.ExecuteNonQuery();
                sqlBatch = string.Empty;
            } else {
                sqlBatch += line + "\n";
            }
        }            
    } finally {
        conn.Close();
    }
}

它要求GO命令位于其自己的行上,并且不会检测到块注释,因此这类事情将被拆分,并导致错误:

ExecuteBatchNonQuery(@"
    /*
    GO
    */", conn);

回答

使用了解GO分隔符的SQL Server管理对象(SMO)。在这里查看我的博客文章:http://weblogs.asp.net/jongalloway/Handling-2200_GO_2200-Separators-in-SQL-Scripts-2D00-the-easy-way

样例代码:

public static void Main()    
{        
  string scriptDirectory = "c:\temp\sqltest\";
  string sqlConnectionString = "Integrated Security=SSPI;" +
  "Persist Security Info=True;Initial Catalog=Northwind;Data Source=(local)";
  DirectoryInfo di = new DirectoryInfo(scriptDirectory);
  FileInfo[] rgFiles = di.GetFiles("*.sql");
  foreach (FileInfo fi in rgFiles)
  {
        FileInfo fileInfo = new FileInfo(fi.FullName);
        string script = fileInfo.OpenText().ReadToEnd();
        using (SqlConnection connection = new SqlConnection(sqlConnectionString))
        {
            Server server = new Server(new ServerConnection(connection));
            server.ConnectionContext.ExecuteNonQuery(script);
        }
   }
}

如果这对我们不起作用,请参阅Phil Haack的库来处理该问题:http://haacked.com/archive/2007/11/04/a-library-for-executing-sql-scripts-with-go-separators -和.aspx

回答

我们可以使用SQL管理对象来执行此操作。这些是Management Studio用于执行查询的对象。我相信Server.ConnectionContext.ExecuteNonQuery()会执行我们需要的操作。

回答

SQL Management Studio本身实际上使用了" GO"批处理分隔符关键字,因此它知道终止发送到服务器的批处理的位置,并且不会传递给SQL Server。如果需要,我们甚至可以在Management Studio中更改关键字。

回答

如果我们不想走SMO路线,则可以搜索并将" GO"替换为";"和查询一样。请注意,将最后一个结果集返回。