GO statements blowing up sql execution in .NET
我有一个非常简单的C命令shell应用程序,它执行由SQL Server生成的用于脚本模式和数据的SQL脚本。这是对"去"声明的吹捧。错误信息:
0以下是完整的SQL脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | /****** Object: Table [gym].[MembershipStatus] Script Date: 9/3/2013 9:24:01 AM ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [gym].[MembershipStatus]( [MembershipStatusID] [tinyint] IDENTITY(1,1) NOT NULL, [Name] [varchar](75) NOT NULL, [Description] [varchar](400) NOT NULL, [AllowCheckin] [bit] NOT NULL, [IncludeInCollections] [bit] NOT NULL, [ScheduleFutureInvoices] [bit] NOT NULL, CONSTRAINT [MembershipStatus_PK] PRIMARY KEY CLUSTERED ( [MembershipStatusID] 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 SET ANSI_PADDING OFF GO SET IDENTITY_INSERT [gym].[MembershipStatus] ON INSERT [gym].[MembershipStatus] ([MembershipStatusID], [Name], [Description], [AllowCheckin], [IncludeInCollections], [ScheduleFutureInvoices]) VALUES (1, N'Active', N'Active', 1, 1, 1) INSERT [gym].[MembershipStatus] ([MembershipStatusID], [Name], [Description], [AllowCheckin], [IncludeInCollections], [ScheduleFutureInvoices]) VALUES (2, N'Cancelled', N'Cancelled', 0, 1, 0) INSERT [gym].[MembershipStatus] ([MembershipStatusID], [Name], [Description], [AllowCheckin], [IncludeInCollections], [ScheduleFutureInvoices]) VALUES (3, N'Collection', N'Collection', 0, 0, 0) INSERT [gym].[MembershipStatus] ([MembershipStatusID], [Name], [Description], [AllowCheckin], [IncludeInCollections], [ScheduleFutureInvoices]) VALUES (4, N'Deleted', N'Deleted', 0, 0, 0) INSERT [gym].[MembershipStatus] ([MembershipStatusID], [Name], [Description], [AllowCheckin], [IncludeInCollections], [ScheduleFutureInvoices]) VALUES (5, N'Expired', N'Expired', 1, 1, 1) INSERT [gym].[MembershipStatus] ([MembershipStatusID], [Name], [Description], [AllowCheckin], [IncludeInCollections], [ScheduleFutureInvoices]) VALUES (6, N'Freeze', N'Freeze', 0, 1, 0) INSERT [gym].[MembershipStatus] ([MembershipStatusID], [Name], [Description], [AllowCheckin], [IncludeInCollections], [ScheduleFutureInvoices]) VALUES (7, N'Inactive', N'Inactive', 0, 1, 1) SET IDENTITY_INSERT [gym].[MembershipStatus] OFF ALTER TABLE [gym].[MembershipStatus] ADD DEFAULT ('') FOR [Name] GO ALTER TABLE [gym].[MembershipStatus] ADD DEFAULT ('') FOR [Description] GO ALTER TABLE [gym].[MembershipStatus] ADD DEFAULT ((0)) FOR [AllowCheckin] GO ALTER TABLE [gym].[MembershipStatus] ADD DEFAULT ((0)) FOR [IncludeInCollections] GO ALTER TABLE [gym].[MembershipStatus] ADD DEFAULT ((0)) FOR [ScheduleFutureInvoices] GO |
我的代码的相关部分如下:
1 2 3 | SqlCommand command = new SqlCommand(script, connection); command.CommandType = CommandType.Text; command.ExecuteNonQuery(); |
有什么想法吗?
正如其他人提到的,用
以下是我使用的方法:
2如果您想使用
然后像这样执行
1 2 3 4 5 6 |
您需要做的是将查询读入一个字符串,然后在
1 2 3 4 5 6 7 8 9 10 11 12 | //Its better to dispose the SqlCommand, I also switched constructors so I could re-use the SqlCommand. using(SqlCommand command = new SqlCommand()) { command.Connection = connection; var scripts = Regex.Split(script, @"^\w+GO$", RegexOptions.Multiline); foreach(var splitScript in scripts) { command.CommandText = splitScript; command.ExecuteNonQuery(); } } |
看看MattJohnson对于
go不是有效的qa命令,它是一个批处理分隔符…它由企业管理器处理以分离SQL脚本。因此,它将在EnterpriseManager中工作,但不在来自C或其他外部程序的数据库调用中工作。
作为通过C_对脚本进行按摩以使其可运行的替代方法,您可以使用
http://technet.microsoft.com/en-us/library/ms180944.aspx
通过使用sqlcmd,您可以编写任何数量的SQL Server生成脚本的执行脚本,而无需剥离
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | string[] commands = sql.Split( new string[]{"GO ","GO","GO\t <p><center>[wp_ad_camp_2]</center></p><hr><P>如另一个答案所述,不支持<wyn>GO</wyn>。</P><P>您可以在脚本上使用<wyn>String.Split()</wyn>,使用<wyn>GO</wyn>语句作为分隔符,并单独运行每个段作为命令。</P><div class="suo-content">[collapse title=""]<ul><li>对于较大的脚本来说,这样的简单拆分可能会很麻烦——假设一些文本将<wyn>GO</wyn>作为文本的一部分,例如列名称或字符串的一部分——或者如果您只查找其中只有<wyn>GO</wyn>的行,则该行可能位于存储过程创建脚本的文本中。</li><li>我同意,通常当我过去必须这样做的时候,我实际上已经分开了,在go语句之前和之后都期望有一个新行。但是正则表达式可能更合适。</li></ul>[/collapse]</div><hr><P>另外1点"iamkrillin"的答案,使用旧的DLL使其工作。</P><P>在添加对这些DLL的引用之后</P><blockquote> <p> Microsoft.SqlServer.ConnectionInfo.dll , Microsoft.SqlServer.Management.Sdk.Sfc.dll Microsoft.SqlServer.Smo.dll , Microsoft.SqlServer.SqlEnum.dll </p> </blockquote><P>从这样的地方:"C:Program Files(x86)Microsoft SQL Server130SDKAssembliesMicrosoft.sql server.connectioninfo.dll"在项目中,我需要在代码文件的顶部添加以下"using"指令:</P>4<hr> <p> The top answer has a mistake. I just tested a working solution: You should allow space,';' or new line before GO </p> [cc lang="csharp"] var scripts = Regex.Split(statementText, @"(\s+|;| | )GO", RegexOptions.Multiline); foreach(var splitScript in scripts.Where(splitScript => !splitScript.IsNullOrWhiteSpace())) { cmd.CommandText = splitScript; cmd.ExecuteNonQuery(); } |