2

我正在创建一个 Web 应用程序,用作执行 SQL 复制的前端。

我有许多脚本存储在程序的属性中。让我们以第一个为例。第一个脚本是您通过在发布服务器上创建出版物获得的脚本。

USE [<<SOURCE_DATABASE_NAME>>]
EXEC sp_replicationdboption @dbname = N'<<SOURCE_DATABASE_NAME>>',
    @optname = N'publish', @value = N'true'
GO
USE [<<SOURCE_DATABASE_NAME>>]
EXEC [<<SOURCE_DATABASE_NAME>>].sys.sp_addlogreader_agent @job_login = N'XXX\Admin',
    @job_password = NULL, @publisher_security_mode = 0,
    @publisher_login = N'Admin', @publisher_password = N'<<PASSWORD>>',
    @job_name = NULL
GO

USE [<<SOURCE_DATABASE_NAME>>]
EXEC sp_addpublication @publication = N'<<SOURCE_DATABASE_NAME>>',
    @description = N'Transactional publication of database ''<<SOURCE_DATABASE_NAME>>'' from Publisher ''<<SOURCE_SERVER_NAME>>''.',
    @sync_method = N'concurrent', @retention = 0, @allow_push = N'true',
    @allow_pull = N'true', @allow_anonymous = N'false',
    @enabled_for_internet = N'false', @snapshot_in_defaultfolder = N'true',
    @compress_snapshot = N'false', @ftp_port = 21,
    @allow_subscription_copy = N'false', @add_to_active_directory = N'false',
    @repl_freq = N'continuous', @status = N'active',
    @independent_agent = N'true', @immediate_sync = N'false',
    @allow_sync_tran = N'false', @allow_queued_tran = N'false',
    @allow_dts = N'false', @replicate_ddl = 1,
    @allow_initialize_from_backup = N'false', @enabled_for_p2p = N'false',
    @enabled_for_het_sub = N'false'
GO

EXEC sp_addpublication_snapshot @publication = N'<<SOURCE_DATABASE_NAME>>',
    @frequency_type = 1, @frequency_interval = 1,
    @frequency_relative_interval = 1, @frequency_recurrence_factor = 0,
    @frequency_subday = 8, @frequency_subday_interval = 1,
    @active_start_time_of_day = 0, @active_end_time_of_day = 235959,
    @active_start_date = 0, @active_end_date = 0,
    @job_login = N'ICS\Admin', @job_password = NULL,
    @publisher_security_mode = 0, @publisher_login = N'Admin',
    @publisher_password = N'<<PASSWORD>>'

我不想在 SQL Management Studio 中运行此脚本,而是想使用我的 Web 应用程序来运行它。

我试过:

public static void CreatePublication(string server, string query)
{
    string finalConnString = Properties.Settings.Default.rawConnectionString.Replace("<<DATA_SOURCE>>", server).Replace("<<INITIAL_CATALOG>>", "tempdb");

     using (SqlConnection conn = new SqlConnection(finalConnString))
     {
         using (SqlCommand cmd = new SqlCommand(query, conn))
         {
             conn.Open();

             cmd.ExecuteNonQuery();
         }
      }
}

public static string ConstructCreatePublicationScript(string rawPublicationScript, string rawAddArticleScript,
            string password, string sourceServerName, string sourceDatabaseName, List<string> selectedTables)
{
    string createPublicationScript = "";
    string addArticleScript = "";

    createPublicationScript = rawPublicationScript.Replace("<<PASSWORD>>", password)
            .Replace("<<SOURCE_SERVER_NAME>>", sourceServerName)
            .Replace("<<SOURCE_DATABASE_NAME>>", sourceDatabaseName);

    createPublicationScript = createPublicationScript + "\n\n";

    foreach (string selectedTable in selectedTables)
    {
        addArticleScript = rawAddArticleScript.Replace("<<SOURCE_DATABASE_NAME>>", sourceDatabaseName)
             .Replace("<<SOURCE_TABLE_NAME>>", selectedTable);

             createPublicationScript = createPublicationScript + addArticleScript + "\n\n";
     }
            //write script to file

            return createPublicationScript;
     }

但是遇到了这个错误:

SqlException 被捕获

'GO' 附近的语法不正确。
'GO' 附近的语法不正确。
'GO' 附近的语法不正确。
'GO' 附近的语法不正确。
'GO' 附近的语法不正确。

我的问题是,如何在 C# 中运行上面的整个脚本?我应该摆脱“GO”关键字吗?

4

3 回答 3

3

更改您的 ConstructCreatePublicationScript 以返回一个List<string>其中每个字符串元素是在 GO 语句处拆分的完整脚本的一部分。这是必要的,因为 GO 是 Management Studio 使用的分隔符,而不是 SQL 语句

public static List<string> ConstructCreatePublicationScript(string rawPublicationScript, string rawAddArticleScript)
{
    .....

    List<string> result = new List<string>();
    result.AddRange(Regex.Split(createPublicationScript, "^GO$", RegexOptions.Multiline));
    return result;
}

然后更改您的执行代码以接收列表并执行每个字符串

public static void CreatePublication(string server, List<string> queries)    
{    
    string finalConnString = Properties.Settings.Default.rawConnectionString.Replace("<<DATA_SOURCE>>", server).Replace("<<INITIAL_CATALOG>>", "tempdb");    

     using (SqlConnection conn = new SqlConnection(finalConnString))    
     {    
         conn.Open();    
         foreach(string query in queries)
         {
             using (SqlCommand cmd = new SqlCommand(query, conn))    
             {    
                 cmd.ExecuteNonQuery();    
             }
         }    
      }    
}
于 2012-09-14T20:41:55.393 回答
2

GO命令不是 SQL 命令,而是 SQL Management Studio 中的命令。它在脚本中分隔批次。

要将脚本作为 SQL 运行,请将其拆分"GO"并单独执行每个字符串。

(您可能希望使用正则表达式\bGO\b\sGO\s进行拆分,以便仅捕获不属于单词的出现,如果您碰巧有一个包含“go”的标识符。)

于 2012-09-14T20:36:51.853 回答
1

读取文件。当您遇到“GO”时,将查询提交到服务器(没有“GO”本身),然后继续阅读。

于 2012-09-14T20:35:55.177 回答