【问题标题】:C#: How to import SQL-script into database programmatically?C#:如何以编程方式将 SQL 脚本导入数据库?
【发布时间】:2010-11-14 13:13:40
【问题描述】:

我必须手动解析 SQL 脚本并分别执行每个语句还是有更好的方法? 我正在寻找一种编程解决方案,我知道有些工具已经能够做到这一点。 如果该解决方案适用于所有数据库系统,而不仅仅是 sqlite,那就太好了。

【问题讨论】:

  • 您是否正在尝试将记录导入您的数据库?
  • 请问您的脚本来自哪里?这些信息很可能会影响答案... Rob

标签: c# sql sqlite parsing ado.net


【解决方案1】:

我不确定这如何适用于 SqlLite,但我在 SqlServer 中使用了如下代码:

protected virtual void ExecuteScript(SqlConnection connection, string script)
{
    string[] commandTextArray = script.Split(new string[] { "GO" }, StringSplitOptions.RemoveEmptyEntries); // See EDIT below!
    connection.Open();
    foreach (string commandText in commandTextArray)
    {
        if (commandText.Trim() == string.Empty) continue;
        SqlCommand command = new SqlCommand(commandText, connection);
        command.ExecuteNonQuery();
    }
    connection.Close();
}

(警告:我不得不稍微修改我的原始代码,所以这是未经测试的代码。)

我发现“GO”这个词在通过 ADO.NET 运行脚本时会出现问题,因此代码对整个脚本执行了 Split() 操作,并以“GO”作为分隔符,然后循环遍历命令数组并一次执行一个。

编辑:

@Mark 在下面的评论中,“GO”可能作为另一个单词的一部分出现在脚本中,这绝对是一个有效的担忧。我记得当我编写上面的代码时,我搜索了我的脚本以确保“GO”仅作为批处理分隔符出现。另一种方法(没有双关语)是编辑所有脚本,以便“GO”后面总是有相同的注释,例如“-- SPLIT HERE!”并将您的分隔符更改为“GO -- SPLIT HERE!”。但是,这需要您编辑脚本。另一个选项是 Regex.Split(),它允许您在 GO 之前检查空格。在我的脚本中,我的批处理分隔符总是单独一行。如果相同的规则适用于您的脚本,则应该可以使用以下内容:

string[] commandTextArray = System.Text.RegularExpressions.Regex.Split(script, "\r\n[\t ]*GO");

最重要的是,批次分隔符需要一些格式一致性才能准确拆分您的脚本。

【讨论】:

  • 注意引号中的 GO、cmets、混合大小写,或者 - 例如 - GO 作为另一个词的一部分。
  • SqlCommand command = new SqlCommand(script, connection);应该是 SqlCommand command = new SqlCommand(commandText, connection);
  • @DanM:您能否详细说明通过 ADO.NET 运行脚本时“GO”这个词是个问题?执行是在第一次 GO 之后停止,还是完全失败?我使用类似的代码,但从未注意到任何问题。在第一次 GO 之后停止可能会被忽视。
  • @Jan,显然现在有一种新的更好的方法来处理这个问题。请查看此链接:weblogs.asp.net/jgalloway/archive/2006/11/07/Handling-2200_GO_2200-Separators-in-SQL-Scripts-2D00-the-easy-way.aspx。此链接还解释了 GO 在 ADO.NET 中存在问题的原因。
【解决方案2】:

使用DbCommand.ExecuteNonQuery 方法,您可以对数据库执行任何SQL。

带有 SqlCommand 的示例:

var command = new SqlCommand("CREATE TABLE foo ...", connection);
command.ExecuteNonQuery();

正如另一个答案中所建议的,如果命令包含“GO”,您可能需要拆分该命令,因为这会将命令拆分为多个批次。

【讨论】:

  • execute 是否能够执行包含许多不同 SQL 语句(包括空行和 cmets)的大字符串?
【解决方案3】:

我不熟悉 SqlLite,但大多数 RDBMS' 将允许您发送多个语句,如果您使用分号结束它们。有些,如 MSSQL,也将接受换行符作为语句终止符。分号 + 换行符是最快乐的,并且也会导致格式良好的代码。

如果你有批处理分隔符——在 MSSQL 中,它通常是“GO”——那么你必须做更多的工作,因为这是由客户端解析的。有一个 couple of solutions 来处理 MSSQL - 但我不知道它们的便携性(如果有的话)。我怀疑 Haack 会是最好的起点。

【讨论】:

    【解决方案4】:

    在以下代码中,Config.Database.CreateCommandText 是一组用分号分隔的语句,用于在数据库中创建表和索引。下面使用 System.Data.SQLite 从无到有创建数据库。

    private SQLiteCommand command;
    private SQLiteConnection connection;
    
    connection = new SQLiteConnection(Config.Database.ConnectionString.ToString());
    connection.Open();
    
    command = connection.CreateCommand();
    
    SQLiteConnection.CreateFile(Config.Database.Path);
    
    command.CommandText = Config.Database.CreateCommandText;
    
    command.ExecuteNonQuery();
    

    【讨论】:

      【解决方案5】:

      我同意 Damm 的回答:Handling "GO" Separators in SQL Scripts - the easy way http://weblogs.asp.net/jgalloway/archive/2006/11/07/Handling-_2200_GO_2200_-Separators-in-SQL-Scripts-2D00-the-easy-way.aspx 您将需要可以在 SQL Server 文件夹“C:\Program Files (x86)\Microsoft SQL Server\100\SDK\Assemblies\”中找到的 DDL

      Microsoft.SqlServer.ConnectionInfo.dll
      Microsoft.SqlServer.Management.Sdk.Sfc.dll
      Microsoft.SqlServer.Smo.dll
      

      还需要兼容的框架,所以在你的配置文件中添加这一行。

      <startup useLegacyV2RuntimeActivationPolicy="true">
          <supportedRuntime version="v4.0" />
      </startup>
      

      这篇文章中给出的答案需要更加完善。例如,处理异常并能够回滚...请查看http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqltransaction.aspx 以获取 SQL 事务中的更多信息。

      【讨论】:

        猜你喜欢
        • 2014-04-07
        • 1970-01-01
        • 2018-11-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多