繁体   English   中英

SQL Server ScriptDom解析

[英]SQL Server ScriptDom Parsing

我与之合作的开发人员团队正在使用SQL数据项目来完成我们必须对现有数据库进行的大量工作。 我们已经进入了几个星期,并且遇到了一些麻烦,但是总体而言,体验还是不错的。

但是,当我们开始进行生产部署时,dba团队拒绝接受DACPAC作为部署方法。 相反,他们希望每个DML或DDL语句看到传统的脚本。

当前的想法是在完成的SQL项目和生产环境之间创建一个差异脚本,然后将其解析为单独的脚本。 我知道不好。

要解析差异脚本,似乎有两个选择:

  1. 根据批处理分隔符命令GO解析脚本。 一个相当基本的解决方案,但显示出希望。
  2. 或者,使用Microsoft.SqlServer.TransactSql.ScriptDom。 这看起来更具前瞻性,但看起来要复杂得多。

我目前正在试用ScriptDom,但无法理解它。 我当前(但不仅是问题)的内容如下。

我正在尝试使用C#中的ScriptDOM解析以下SQL:

CREATE TABLE dbo.MyTable
(
    MyColumn VARCHAR(255)
)

但是看不到如何访问VARCHAR大小,在这种情况下为255。

我使用的代码如下:

TSqlFragment sqlFragment = parser.Parse(textReader, out errors);

SQLVisitor myVisitor = new SQLVisitor();
sqlFragment.Accept(myVisitor);

public override void ExplicitVisit(CreateTableStatement node)
{
    // node.SchemaObjectName.Identifiers to access the table name
    // node.Definition.ColumnDefinitions to access the column attributes
}

我希望从每个列定义中找到一个length属性或类似的属性。 但是,我也有一个偷偷摸摸的怀疑,就是您可以使用我所苦恼的“访客模式”来重新解析每个列的定义。 有任何想法吗?

太棒了,您正在使用ssdt!

当您有不想使用dacpacs的DBA时,处理此问题的最简单方法是使用sqlpackage.exe预先生成部署脚本。

我的方式是...

  • 将T-SQL代码检入项目
  • 构建服务器构建ssdt项目
  • 在CI服务器上部署和运行测试
  • 使用sqlpackage.exe / action:script将dacpac与QA,PROD等进行比较,并生成部署脚本。

然后,DBA将使用该脚本(或者,当我们准备好了之后,我们告诉他们要获取的内部版本号)-他们可以细读并部署该脚本。

注意事项:

如果没有CI安装程序,则可以使用sqlpackage.exe生成没有自动位的脚本:)

希望能帮助到你!

我认为您根本不需要访客。 如果我正确理解了您的目标,则希望使用SSDT生成的TSQL,使用SQLDOM进行解析,然后分别打印批处理。 这样做的代码如下所示:

using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.SqlServer.TransactSql.ScriptDom;

namespace ScriptDomDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            TSql120Parser parser = new TSql120Parser(false);
            IList<ParseError> errors;
            using (StringReader sr = new StringReader(@"create table t1 (c1 int primary key)
GO
create table t2 (c1 int primary key)"))
            {
                TSqlFragment fragment = parser.Parse(sr, out errors);
                IEnumerable<string> batches = GetBatches(fragment);
                foreach (var batch in batches)
                {
                    Console.WriteLine(batch);
                }
            }
        }

        private static IEnumerable<string> GetBatches(TSqlFragment fragment)
        {
            Sql120ScriptGenerator sg = new Sql120ScriptGenerator();
            TSqlScript script = fragment as TSqlScript;
            if (script != null)
            {
                foreach (var batch in script.Batches)
                {
                    yield return ScriptFragment(sg, batch);
                }
            }
            else
            {
                // TSqlFragment is a TSqlBatch or a TSqlStatement
                yield return ScriptFragment(sg, fragment);
            }
        }

        private static string ScriptFragment(SqlScriptGenerator sg, TSqlFragment fragment)
        {
            string resultString;
            sg.GenerateScript(fragment, out resultString);
            return resultString;
        }
    }
}

至于如何使用这些AST,我发现最简单的方法是使用Visual Studio的调试器将树可视化,因为您可以看到每个节点的实际类型及其所有属性。 如您所见,只需少量代码即可解析TSQL。

#reference Microsoft.SqlServer.BatchParser
#reference Microsoft.SqlServer.BatchParserClient

using System;
using System.Collections.Specialized;
using System.IO;
using System.Text;
using Microsoft.SqlServer.Management.Common;

namespace ScriptParser
{
   class Program
   {
      static void Main(string[] args)
      {
         ExecuteBatch batcher = new ExecuteBatch();
         string text = File.ReadAllText("ASqlFile.sql");
         StringCollection statements = batcher.GetStatements(text);
         foreach (string statement in statements)
         {
            Console.WriteLine(statement);
         }
      }
   }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM