【问题标题】:How to Dynamically Create Views?如何动态创建视图?
【发布时间】:2015-05-02 03:59:56
【问题描述】:

背景

我有一个显示客户独有数据的网站。每次添加新客户端时,该站点都需要创建视图。每个客户都是独一无二的,并且具有他们独有的不同识别信息。例如 ID 号和前缀。

每次添加新客户端时,都会使用标准视图集手动创建一组新视图,每次都会更改以反映客户端的唯一信息。这通常使用 SQL Server Management Studio (SSMS) 中的查找和替换来完成

到目前为止我有什么?

我创建了一个 Winform 应用程序,它捕获唯一信息并将它们放入变量中。然后将这些变量放入用于创建视图的标准脚本中。

问题

我的脚本包含的 SMSS 语句不是原生 SQL 语句,这会导致我的程序出错并在提交到数据库时中断。

有问题的语句是 SMSS 用于运行批处理的 GO关键字。

到目前为止我尝试了什么?

我已经使用 String Literal 封装了整个脚本,并按照另一个问题中的建议在 GO 语句之前和之后插入了一个新行。但它似乎不起作用。

我现在正在尝试什么?

使用 REGEX 在每次出现“GO”时拆分脚本。这也行不通。

问题

这个问题有更好的解决方案或我的解决方案吗?

代码

 string connectionString = fmDbSelect();
            using (SqlConnection connection = new SqlConnection(connectionString))
            {

                using (SqlCommand command = new SqlCommand())
                {
                    command.Connection = connection;
                    connection.Open();
                    var scripts = Regex.Split(sql, @"^\w+GO$", RegexOptions.Multiline);
                    foreach (var splitScript in scripts)
                    {
                        command.CommandText = splitScript;
                        command.ExecuteNonQuery();

                    }


                }
            }

错误信息

{"'ANSI_NULLS' 附近的语法不正确。\r\n附近的语法不正确 'QUOTED_IDENTIFIER'。\r\n')' 附近的语法不正确。\r\n语法不正确 'ANSI_NULLS' 附近。\r\n附近有不正确的语法 'QUOTED_IDENTIFIER'。\r\n')' 附近的语法不正确。\r\n'CREATE VIEW' 必须是查询批处理中的第一条语句。\r\n附近的语法不正确 ')'。\r\n')' 附近的语法不正确。\r\n附近的语法不正确 ')'。\r\n'ANSI_NULLS' 附近的语法不正确。\r\n附近的语法不正确 “ANSI_NULLS”。\r\n关键字“AS”附近的语法不正确。\r\n不正确 关键字“AS”附近的语法。\r\n关键字附近的语法不正确 “AS”。\r\n关键字“AS”附近的语法不正确。\r\n语法不正确 关键字“AS”附近。\r\n关键字附近的语法不正确 “AS”。\r\n“ANSI_NULLS”附近的语法不正确。\r\n附近的语法不正确 ')'。\r\n'ANSI_NULLS' 附近的语法不正确。\r\n附近的语法不正确 “ANSI_NULLS”。\r\n“ANSI_NULLS”附近的语法不正确。\r\n不正确 关键字“AS”附近的语法。\r\n关键字附近的语法不正确 “AS”。\r\n“ANSI_NULLS”附近的语法不正确。\r\n附近的语法不正确 ')'。\r\n'ANSI_NULLS' 附近的语法不正确。\r\n附近的语法不正确 ')'。\r\n'ANSI_NULLS' 附近的语法不正确。\r\n附近的语法不正确 “ANSI_NULLS”。\r\n“ANSI_NULLS”附近的语法不正确。\r\n不正确 ')' 附近的语法。\r\n'ANSI_NULLS' 附近的语法不正确。\r\n不正确 关键字“AS”附近的语法。\r\n关键字附近的语法不正确 “AS”。\r\n“ANSI_NULLS”附近的语法不正确。\r\n附近的语法不正确 “ANSI_NULLS”。\r\n“ANSI_NULLS”附近的语法不正确。\r\n不正确 'ANSI_NULLS' 附近的语法。\r\n')' 附近的语法不正确。\r\n不正确 'ANSI_NULLS' 附近的语法。\r\n附近的语法不正确 “ANSI_NULLS”。\r\n关键字“AS”附近的语法不正确。\r\n不正确 关键字“LIKE”附近的语法。\r\n附近的语法不正确 'ANSI_NULLS'。"}

我的脚本

/****** 对象:查看 [dbo].[TIDEreportEmails] 脚本日期: 23/02/2015 12:43:36 ******/ 开始设置 ANSI_NULLS

SET QUOTED_IDENTIFIER ON GO

创建视图 [dbo].[TIDEreportEmails] 选择电子邮件 ID, EmailContent、EmailSubject、EmailTo、EmailFrom、UserID、ObjectValueID、 EmailSent、EmailCreated、EmailRead、EmailFromName、EmailType、 电子邮件失败, 案例 WHEN emailread 为 NULL THEN 'Not Read' ELSE 'Read' END AS EmailStatus FROM DEReportingClient2DB.dbo.Emails AS Emails_1 WHERE(用户 ID IN (选择用户 ID FROM DEReportingClient2DB.dbo.Users WHERE (ClientID = 195)))

/****** 对象:查看 [dbo].[TIDEunreadEmails] 脚本日期: 23/02/2015 12:43:36 ******/ 开始设置 ANSI_NULLS

SET QUOTED_IDENTIFIER ON GO

创建视图 [dbo].[TIDEunreadEmails] AS SELECT COUNT(*) AS UnreadEmails, UserID FROM dbo.TIDEreportEmails WHERE
(EmailRead 为 NULL)按用户 ID 分组

【问题讨论】:

  • 这些错误的原因:GO 这不是 T-SQL 关键字。解决方案:见Remus's answer

标签: c# sql-server regex string


【解决方案1】:

您的正则表达式无法正确分割行;您可以使用以下语句之一来拆分脚本。

  1. sql.Split(new string[] { "GO" }.
  2. Regex.Split(sql, @"\bGO\b", RegexOptions.Multiline);

下面是代码-sn-p

      string connectionString = fmDbSelect();
        using (SqlConnection connection = new SqlConnection(connectionString))
        {

            using (SqlCommand command = new SqlCommand())
            {
                command.Connection = connection;
                connection.Open();
                var scripts = Regex.Split(sql, @"\bGO\b", RegexOptions.Multiline);
                //var scripts = sql.Split(new string[] { "GO" }, StringSplitOptions.None);
                foreach (var splitScript in scripts)
                {
                    command.CommandText = splitScript;
                    command.ExecuteNonQuery();

                }


            }
        }

【讨论】:

    【解决方案2】:

    删除 GO 语句。

    SSMS 使用 GO 将单独的“批次”发送到 SQL Server……它只不过是一个分隔符。大多数你不需要的 GO。

    如果某些内容必须是批处理中的第一件事(例如 CREATE VIEW 语句),只需在一个批处理中发送之前的所有内容,然后在单独的语句中,将完整的 CREATE VIEW 语句作为代码中的单独步骤发送.

    您可以并且应该使用相同的连接对象,只需发送一个命令,然后发送一个不同的命令,每批一个。并且没有必要将“SET”语句与 GO 分开。您可以将所有 SET 语句放在一起......并且您可以在连接上只执行一次。所以...使用一个命令来发送 SET 语句。然后一个命令单独发送每个 CREATE VIEW 语句。

    【讨论】:

      【解决方案3】:

      GO 上进行拆分如果操作正确。您只是不正确地拆分。使用调试器检查您尝试执行的内容。很明显会坏掉的。

      确保您没有将GO 发送到服务器。

      您的脚本中的换行符似乎搞砸了。也许这只是在此处获取脚本的一种人工制品。

      【讨论】:

        猜你喜欢
        • 2012-05-18
        • 1970-01-01
        • 1970-01-01
        • 2016-05-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-24
        相关资源
        最近更新 更多