2013-04-29 9 views
5

Mam bardzo duży plik sql Chcę podzielić na partie do wykonania. Chcę się upewnić, że parsuję to w taki sam sposób, jak SSMS i SQLCMD.W jaki sposób analizować duże skrypty SQL w partiach?

Firma Microsoft ma świetny zestaw trybów mieszanych o nazwie Microsoft.SqlServer.BatchParser z klasą o nazwie Parser, która łączy się tak, jakby to było możliwe.

Chce wdrożyć IBatchSource jako argument do SetBatchSource przed wywołaniem funkcji Parse().

Gdzie mogę znaleźć implementację IBatchSource i więcej informacji na temat korzystania z tej funkcji?

Odpowiedz

12

Znalazłem zespół Microsoft.SqlServer.BatchParser w GAC wraz z jego przyjacielem Microsoft.SqlServer.BatchParserClient, który zawiera implementacje interfejsu IBatchSource.

namespace Microsoft.SqlServer.Management.Common 
{ 
    internal class BatchSourceFile : IBatchSource 
    internal class BatchSourceString : IBatchSource 
} 

Następnie następująca rozmowa.

Montaż: Witam! Nazywam się Microsoft.SqlServer.Management.Common.ExecuteBatch. Czy chcesz StringCollection GetStatements (ciąg sqlCommand)?

Ja: Tak, chciałbym, montaż BatchParserClient. Dzięki, że pytasz!

Powtarzalne Instrukcje (Nie próbujcie tego w domu!)

  • Install Microsoft SQL Server 2008 R2 Shared Management Objects
  • Copy Microsoft.SqlServer.BatchParser.dll i Microsoft.SqlServer.BatchParserClient.dll z GAC Do folder w twoim rozwiązaniu.
  • referencyjny Microsoft.SqlServer.BatchParser & Microsoft.SqlServer.BatchParserClient

Program.cs

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(@"Path_To_My_Long_Sql_File.sql"); 
     StringCollection statements = batcher.GetStatements(text); 
     foreach (string statement in statements) 
     { 
      Console.WriteLine(statement); 
     } 
     } 
    } 
} 

app.config

<?xml version="1.0"?> 
<configuration> 
    <startup useLegacyV2RuntimeActivationPolicy="true"> 
     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/> 
    </startup> 
</configuration> 

Inną opcją jest użycie ScriptDom jak opisano w ta odpowiedź: https://stackoverflow.com/a/32529415/26877.

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; 
     } 
    } 
} 
+0

Przepraszam, ale 'File.ReadAllText' nadal będzie najpierw czytał cały plik w pamięci. Więc z dużymi plikami (może nierozsądnie dużymi, ale nadal) masz problemy. Zasadniczo wymagany byłby interfejs "przesyłania strumieniowego". Jak już zauważyłem [tutaj] (http://stackoverflow.com/a/12154400/21567), 'SQLCMD.EXE' jest w stanie to zrobić, i prawdopodobnie używa również' IBatchSource', choć natywna implementacja, a nie opakowanie "managed". Pozostaje pytanie: jak podzielić tekst wejściowy na porcje, aby BatchParser mógł to zrozumieć. (+1, ale nadal, za dobry wkład) –

+0

@ Christian.K znaleźć odpowiedź https: // stackoverflow.com/a/32529415/26877, która może być opcją do analizowania twoich partii za pomocą skryptu ScriptDOM. – JJS

Powiązane problemy