【问题标题】:Execute sql file on SQL Server using C#使用 C# 在 SQL Server 上执行 sql 文件
【发布时间】:2011-01-26 18:04:19
【问题描述】:

我有很多用于过程、视图、函数等的文件。

我想在 SQL Server 2005/2008 上的适当数据库中执行这些文件(创建组件)。

还有一点是我想用 C# 来执行它们。

还有一点要提一下,我希望应用程序能够在远程 SQL Server 上执行这些文件。另外客户端机器可能没有osql,sqlcmd命令工具。

有人可以指导我吗?

【问题讨论】:

  • 你能解释一下这些文件是什么。你想创建一个 .net dll 组件来在 c# 代码中执行这些功能吗?
  • 文件是普通的 .sql 文件。不,我不想创建 dll 组件。我只想安装一次。

标签: c# sql-server-2005 sql-server-2008 stored-procedures installation


【解决方案1】:

这取决于它们是什么类型的文件。例如,如果它们包含实际的 T-SQL 命令(并且不是您将在其中运行的 batch 文件,例如 SSMS,它将包含一个批处理分隔符如GO),那么您只需要创建一个连接、一个命令,然后读取文件的内容并使用它来填充命令的CommandText 属性。

例如:

void ExecuteFile(string connectionString, string fileName)
{
    using(SqlConnection conn = new SqlConnection(connectionString))
    {
        string data = System.IO.File.ReadAllText(fileName);

        conn.Open();

        using(SqlCommand cmd = conn.CreateCommand())
        {
            cmd.CommandText = data;
            cmd.ExecuteNonQuery();
        }
    }
}

如果是批处理文件,您需要将文件拆分为单独的批处理并单独处理。最简单的方法就是使用string.Split,但切记在拆分时它不会遵守SQL解析规则(例如,如果GO出现在SQL语句中,它会将命令拆分为两个批次,这显然会失败)。

更一般地说,您可以通过以这种方式修改代码来查看您需要在此处执行的操作:

string[] batches = SplitBatches(System.IO.File.ReadAllText(fileName));

conn.Open();

using(SqlCommand cmd = conn.CreateCommand())
{
    foreach(string batch in batches)
    {
        cmd.CommandText = batch;
        cmd.ExecuteNonQuery();
    }
}

名为SplitBatches 的函数的实现由您决定。

【讨论】:

  • 感谢您的回答。但我还是有些怀疑。在 .sql 文件中,我有这样的代码 >if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[usp_CheckID]') and > OBJECTPROPERTY(id, N'IsProcedure') = 1 ) >drop procedure [dbo].[usp_CheckID] >GO //创建过程的代码
  • 因此在执行文件时出现错误“GO”附近的语法不正确。 'CREATE/ALTER PROCEDURE' 必须是查询批处理中的第一条语句。关键字“else”附近的语法不正确。 'GO' 附近的语法不正确。
  • @Sunil:你有一个批处理文件;请参阅我关于如何处理的答案的第二部分。 GO 命令不是 SQL 命令,它只是一个标准字符串,用于在 SSMS 或 Visual Studio 中分隔 SQL 批处理。如果您想以这种方式处理它们,您必须自己拆分批次。
【解决方案2】:

通常,最简单的方法是在“GO”语句上拆分脚本并分别执行每个项目。如果脚本在注释中包含 GO 语句,此解决方案将不起作用。

private readonly Regex _sqlScriptSplitRegEx = new Regex( @"^\s*GO\s*$", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled );
public void ExecuteSqlScript( string scriptText )
{
    if ( string.IsNullOrEmpty( scriptText ) )
        return;

    var scripts = _sqlScriptSplitRegEx.Split( scriptText );
    using ( var conn = new SqlConnection( "connection string" ) )
    {
        using ( var ts = new TransactionScope( TransactionScopeOption.Required, new TimeSpan( 0, 10, 0 ) ) )
        {
            foreach ( var scriptLet in scripts )
            {
                if ( scriptLet.Trim().Length == 0 )
                    continue;

                using ( var cmd = new SqlCommand( scriptLet, conn ) )
                {
                    cmd.CommandTimeout = this.CommandTimeout;
                    cmd.CommandType = CommandType.Text;
                    cmd.ExecuteNonQuery();
                }
            }

            ts.Complete();
        }
    }
}

【讨论】:

    【解决方案3】:

    通常您只需使用SqlCommand.ExecuteNonQuery 执行它们,一次一批。剩下的任务就是使用当前设置的批处理分隔符(通常是GO)将脚本分成批处理。免费库 dbutilsqlcmd 可用于处理 SQL 脚本,因为它不仅处理分隔符,还处理 SQLCMD 扩展(:setvar:connect 等)。

    【讨论】:

      【解决方案4】:

      使用标准 ADO 会“工作”——例如,可以使用 SqlCommand.ExecuteNonQuery 发送 SQL DDL。

      ...但我建议使用数据库项目(带有远程登台部署或 VSDBCMD)或 SQLCMD(可能与 PowerShell 脚本结合使用 :-) 或 SQL Management Studio 等工具之一。它们是为这类东西设计的。

      【讨论】:

      • 对不起,我不想使用 SQLCMD,因为我想将这些文件从我的机器(没有 osql、sqlcmd)执行到远程机器(这里安装了 sql server)
      • @Sunil Agarwal VSDBCMD(可能还有 SQLCMD)可以“打包”用于远程部署,无需安装。请参阅2008 Feature Pack,其中可能包含其他实用程序(可能需要安装,但可能能够在没有安装的情况下运行它们,没有尝试)。如果可以通过网络访问目标机器(从您当前的机器或登台机器),那么这只是“简单的方法”;-) 希望您能找到一个不错的解决方案。还有第三方工具。
      • @Sunil Agarwal 使用数据库项目(VSDBCMD 部署是一个选项)到另一个数据库特定项目工具(例如第 3 方)的一个原因是能够轻松生成/比较/合并更改等. (虽然,除了初始导入之外,我还没有找到如何成功使用 VSDBCMD 进行任何操作。但 VSDBCMD 对于初始导入确实非常有效。)此外,VSDBCMD 的中间结果是(一个大的,但很简单)SQL 文件,它本身可能会使部署更容易。 我没有玩过额外的捕获或部署形式,例如“脚本更改”。
      【解决方案5】:

      您可以使用 TextReader 读取命令,然后使用 ExecuteNonQuery 和 TextReader 结果作为命令。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-01-04
        • 1970-01-01
        • 2011-08-17
        • 2021-12-28
        • 1970-01-01
        • 2010-10-31
        • 1970-01-01
        相关资源
        最近更新 更多