1

私が一緒に働いている開発者チームは、既存のデータベースに対して行う必要がある大規模な作業に SQL Data Projects を使用しています。私たちは数週間で、いくつかの落とし穴がありましたが、経験は一般的に良好です.

ただし、本番環境にデプロイするとき、dba チームは DACPAC をデプロイ方法として受け入れることを拒否しました。代わりに、DML または DDL ステートメントごとに従来のスクリプトを見たいと考えています。

現在の考えでは、完成した SQL プロジェクトと本番環境の間で差分スクリプトを作成し、それを個別のスクリプトに解析します。良くないね。

差分スクリプトを解析するには、次の 2 つのオプションがあるようです。

  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
}

各列の定義から、長さのプロパティなどを見つけることが期待されていました。ただし、私が苦労している訪問者パターンを使用して、各列定義を再解析できるのではないかという疑念も潜んでいます。何か案は?

4

3 に答える 3

3

ここに来客は必要ないと思います。私があなたの目標を正しく理解している場合は、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 を解析するのに必要なコードはわずかです。

于 2015-09-11T17:53:43.577 に答える
3

あなたがssdtを使っているのは素晴らしいことです!

dacpacs を使用したくない DBA がいる場合にこれを処理する最も簡単な方法は、sqlpackage.exe を使用してデプロイ スクリプトを事前に生成することです。

私のやり方は…

  • t-sql コードをプロジェクトにチェックインする
  • ビルド サーバーは ssdt プロジェクトをビルドします
  • ci サーバーにテストをデプロイして実行する
  • sqlpackage.exe /action:script を使用して、dacpac を QA、PROD などと比較し、展開スクリプトを生成します。

次に、DBA はそのスクリプトを取得します (または、準備が整ったら取得するビルド番号を伝えます)。DBA はそのスクリプトを熟読して展開できます。

注意事項:

CI セットアップがない場合は、sqlpackage.exe を使用して、自動ビットなしでスクリプトを生成できます:)

それが役に立てば幸い!

エド

于 2015-09-11T13:08:16.723 に答える
0
#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);
         }
      }
   }
}
于 2017-05-25T17:35:00.240 に答える