2013-04-29 31 views
5

Tôi có một tập tin sql rất lớn Tôi muốn chia tay vào lô để thực hiện. Tôi muốn chắc chắn rằng tôi đang phân tích nó theo cách tương tự mà SSMS và SQLCMD làm.Làm cách nào để phân tích cú pháp các tập lệnh SQL lớn thành các lô?

Microsoft có một hội đồng chế độ hỗn hợp vĩ đại tên là Microsoft.SqlServer.BatchParser với một lớp có tên Parser rằng vỉa như nó sẽ làm các trick.

Nó muốn một thực hiện IBatchSource như một cuộc tranh cãi để SetBatchSource trước khi gọi Parse().

Tôi có thể tìm thấy một thực hiện IBatchSource, và thêm thông tin về làm thế nào để tận dụng chức năng này ở đâu?

Trả lời

12

Tôi đã tìm thấy tập hợp Microsoft.SqlServer.BatchParser trong GAC cùng với người bạn đó là Microsoft.SqlServer.BatchParserClient có chứa triển khai giao diện IBatchSource.

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

Cuộc hội thoại sau đó xảy ra.

Lắp ráp: Xin chào! Tên tôi là Microsoft.SqlServer.Management.Common.ExecuteBatch. Bạn có muốn StringCollection GetStatements (chuỗi sqlCommand) không?

Tôi: Có, tôi sẽ, lắp ráp BatchParserClient. Cam ơn vi đa hỏi!

Hướng dẫn lặp (Đừng thử loại này ở nhà!)

  • Install Microsoft SQL Server 2008 R2 Shared Management Objects
  • Sao chép Microsoft.SqlServer.BatchParser.dll và Microsoft.SqlServer.BatchParserClient.dll từ GAC đến một trong thư mục của bạn.
  • Reference 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> 

Một lựa chọn khác là sử dụng ScriptDom như được mô tả trong câu trả lời này: 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

Xin lỗi, nhưng 'Tệp.ReadAllText' sẽ vẫn đọc toàn bộ tệp vào bộ nhớ trước. Vì vậy, với các tập tin lớn (có thể không hợp lý lớn, nhưng vẫn còn), bạn có vấn đề. Về cơ bản, một giao diện "streaming" sẽ được yêu cầu. Như tôi đã lưu ý [ở đây] (http://stackoverflow.com/a/12154400/21567), 'SQLCMD.EXE' có thể làm điều đó, và có lẽ cũng sử dụng' IBatchSource', mặc dù việc thực hiện tự nhiên chứ không phải "wrapper" được quản lý. Câu hỏi vẫn còn là: làm thế nào để tách văn bản đầu vào thành các khối để BatchParser có thể hiểu được nó. (+1 mặc dù vẫn còn, cho một đóng góp tốt) –

+0

@ Christian.K tìm thấy câu trả lời https: // stackoverflow.com/a/32529415/26877 có thể là một tùy chọn để phân tích cú pháp các lô của bạn bằng ScriptDOM. – JJS

Các vấn đề liên quan