Синтаксический анализ SQL Server ScriptDom

Команда разработчиков, с которыми я работаю, использует проекты данных SQL для большой части работы, которую мы должны выполнить с существующей базой данных. Мы находимся в течение нескольких недель, и было несколько ошибок, но опыт в целом был хорошим.

Однако, когда мы начинаем развертывание в производство, команда dba отказалась принять DACPAC в качестве метода развертывания. Вместо этого они хотят видеть традиционный скрипт для каждого оператора DML или DDL.

В настоящее время предполагается создать разностный сценарий между готовым проектом SQL и производственной средой, а затем проанализировать его в отдельных сценариях. Не хорошо, я знаю.

Для разбора скрипта разницы, кажется, есть два варианта:

  1. Разбор скрипта на основе команды пакетного разделения, GO. Довольно простые решения, но многообещающие.
  2. Или используйте Microsoft.SqlServer.TransactSql.ScriptDom. Это выглядит более перспективным на будущее, но кажется гораздо более сложным.

Я сейчас пробую ScriptDom, но у меня проблемы с его пониманием. Мои текущие, но не только проблемы, заключаются в следующем.

Я пытаюсь проанализировать следующий SQL с помощью ScriptDOM в C#:

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
}

Из каждого определения столбца я ожидал найти свойство длины или подобное. Однако у меня также есть подозрение, что вы можете использовать Шаблон посетителя, с которым я борюсь, для повторного анализа каждого определения столбца. Есть идеи?

3 ответа

Решение

Здорово, что вы используете ssdt!

Самый простой способ справиться с этим, когда у вас есть администраторы баз данных, которые не хотят работать с dacpacs, - это предварительно сгенерировать сценарий развертывания, используя sqlpackage.exe.

То, как я это делаю, это...

  • Проверьте код t-sql в проект
  • Сборка сервера сборок проекта ssdt
  • Развертывание и запуск тестов на ci сервере
  • используйте sqlpackage.exe /action:script, чтобы сравнить dacpac с QA, PROD и т. д. и сгенерировать сценарий развертывания.

Затем администраторы баз данных берут этот сценарий (или, когда мы будем готовы, мы сообщаем им номер сборки, чтобы получить) - они могут просмотреть и развернуть этот сценарий.

Что следует отметить:

  • Вам понадобится доступ к prod db или к зеркальной копии, которую вы можете использовать, вам не нужны dbo или что-то еще, только разрешения ( https://the.agilesql.club/Blogs/Ed-Elliott/What-Permissions-Do-I-Need-To-Generate-A-Deploy-Script-With-SSDT)
  • Сценарии действительны только до тех пор, пока схема в prod db не изменится - поэтому, если вы сгенерируете 4 сценария и запустите сценарий 1, остальные три будут недействительными, и вам потребуется перезапустить сборку для создания сценария.

Если у вас нет настройки CI, вы можете просто использовать sqlpackage.exe для генерации скрипта без автоматических битов:)

Надеюсь, поможет!

издание

Я не думаю, что вам нужен посетитель здесь вообще. Если я правильно понимаю вашу цель, вы хотели бы взять TSQL, сгенерированный SSDT, проанализировать его с помощью 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);
         }
      }
   }
}
Другие вопросы по тегам