【问题标题】:How to execute SQL with comments and GO statements using SqlConnection?如何使用 SqlConnection 执行带有注释和 GO 语句的 SQL?
【发布时间】:2010-12-05 03:16:50
【问题描述】:

我似乎无法执行使用 DbCommand 对象创建数据库的 SQL。我究竟做错了什么?这是我的代码:

DbConnection connection; // initialized and opened elsewhere
DbCommand cmd = connection.CreateCommand();
cmd.CommandText = sql;
cmd.ExecuteNonQuery();

这是错误:

查询语法无效。,接近 术语“/”,第 1 行,第 2 列。 描述:未处理的异常 在执行过程中发生 当前的网络请求。请查看 堆栈跟踪以获取有关的更多信息 错误及其起源 代码。

异常详情: System.Data.EntitySqlException: 查询语法无效。,近期 '/',第 1 行,第 2 列。

这是文件的第一部分。仅针对第一行的 cmets 引发异常:

/****** Object:  Table [dbo].[User]    Script Date: 10/08/2009 12:14:29 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[User](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [FirstName] [nvarchar](50) NULL,
    [LastName] [nvarchar](50) NULL,
    [EmailAddress] [nvarchar](100) NULL,
 CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

同样的 SQL 脚本在 SQL Management Studio Express 中执行得很好(实际上是应用程序生成了这个脚本!)。这只是 Visual Studio 自己的服务器资源管理器查询视图和我自己的代码似乎失败了。

【问题讨论】:

  • 注意:GO 不是 SQL 命令,它是对客户端工具(例如 OSQL、查询分析器,或者本例中的 SMSS。)的命令,用于将脚本分成单独的“批次”。每个批次都是对服务器的单独调用。

标签: c# sql database


【解决方案1】:

您需要使用 SQL 管理类而不是普通的 SqlCommand。 This page shows you how to do it. 如果您尝试自己解析 SQL,那么总会有您错过的边缘情况。例如,如果代码中的字符串包含带有前导和尾随回车符的单词“GO”怎么办?

添加这些引用:

  • Microsoft.SqlServer.Smo
  • Microsoft.SqlServer.ConnectionInfo
  • Microsoft.SqlServer.Management.Sdk.Sfc(编辑:不需要此引用)

那么你就可以使用这段代码了:

string connectionString, scriptText;
SqlConnection sqlConnection = new SqlConnection(connectionString);
ServerConnection svrConnection = new ServerConnection(sqlConnection);
Server server = new Server(svrConnection);
server.ConnectionContext.ExecuteNonQuery(scriptText);

【讨论】:

  • 太棒了。我找不到要引用的 Microsoft.SqlServer.Management.Sdk.Sfc 程序集,但事实证明它没有必要。
【解决方案2】:

这是我前段时间posted on my blog的一个代码sn-p,可能会解决这个问题:

private static void RunScript(SqlConnection connection, string script)
{
    Regex regex = new Regex(@"\r{0,1}\nGO\r{0,1}\n");
    string[] commands = regex.Split(script);

    for (int i = 0; i < commands.Length; i++)
    {
        if (commands[i] != string.Empty)
        {
            using(SqlCommand command = new SqlCommand(commands[i], connection))
            {
                command.ExecuteNonQuery();
                command.Dispose();
            }
        }
    }
}

它将 SQL 脚本拆分为单独的命令并执行每个命令。我经常使用它来设置带有生成的 SQL 脚本的测试数据库。

【讨论】:

  • +1,但我不认为这是这里的唯一问题。错误是抱怨文件顶部的注释。
  • @Joel:我认为它可能实际上抱怨完整的声明,而这恰好从评论开始。不过不能确定,所以我对文本进行了编辑,以不太确定它是否提供了解决方案。
  • GO 批处理分隔符被空格包围是有效的,至少在 SQL Server 2005 的 SMSS 中。
  • @Mork: command.Dispose() 不再需要,因为它在 using 语句中
  • 即使处理复杂的东西也能发挥魅力
【解决方案3】:

我觉得奇怪的是你得到了一个 EntitySqlException ...

您可以选择的另一种解决方案是通过 osql 命令行工具执行此脚本。 您可以创建一个 System.Diagnostics.Process 实例,并使用此进程调用 osql,后者依次执行脚本。

System.Diagnostics.Process p = new System.Diagnostics.Process ();

p.StartInfo.FileName = Environment.GetEnvironmentVariable ("COMSPEC");
p.StartInfo.UseShellExecute = false;
p.StartInfo.ErrorDialog = false;

p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardOutput = true;

p.Start ();

p.StandardInput.WriteLine ("echo off");
string command = @"osql -U -b -e -S " + servername + " -d " + databasename + " -i \'" + filename + "\'";
p.StandardInput.WriteLine (command);
p.StandardInput.WriteLine ("exit");

p.WaitForExit ();

【讨论】:

  • 感谢您的提示。这在我的另一个场景中可能很有用。
【解决方案4】:

在 SQL Server 中,您可以使用简单的空格分隔符连接任意数量的查询,但为此您需要删除“GO”。
例子:

BEGIN TRANSACTION SET QUOTED_IDENTIFIER ON SET ARITHABORT ON SET NUMERIC_ROUNDABORT OFF SET CONCAT_NULL_YIELDS_NULL ON SET ANSI_NULLS ON SET ANSI_PADDING ON SET ANSI_WARNINGS ON COMMIT BEGIN TRANSACTION $remove this GO here$ CREATE TABLE dbo.Tmp_Tralala( ERRID numeric (18, ) ) ON [PRIMARY] $remove this GO here$ IF EXISTS(SELECT * FROM dbo.Tralala) EXEC('INSERT INTO ..etc

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-06-14
    • 1970-01-01
    • 2011-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-06
    • 2016-11-02
    相关资源
    最近更新 更多