2016-08-10 43 views
1

我期待能夠採取的MDX字符串是這樣的:CLR函數解析MDX字符串

[Event Product].[Event Category Filter].[Category Group].&[E].&[F].&[G].&[H] 

,並使用正則表達式來單獨解析出的第一,第二和第三串方括號。

因此,理想情況3個,將返回定製的regex表達式:

Event Product 

Event Category Filter 

Category Group 

第四分組及以後可以選配(雖然前三將始終存在)。這將是巨大的,具有能夠在限定的一行回國後,以後每場比賽的第四表達,所以像:

E,F,G,H 

我拍攝的第一組:

((?<=\[)(.*?)(?=\])) 

然而我正在努力排除第n部分。

任何人都可以在這裏伸出援手嗎? :)

編輯:

如果已經提到了這一點前期,我們使用正則表達式組件腳本和香草T-SQL這樣做。

https://www.simple-talk.com/sql/t-sql-programming/clr-assembly-regex-functions-for-sql-server-by-example/

A C#的解決方案是什麼,我想最終要使用,但暫時純粹的正則表達式的解決方案將是最好的。我主要使用非點網絡堆棧,因此,就我們的ETL而言,我們沒有一個完整的工具包可用。

+0

方括號之間允許使用哪些字符? –

+0

SQL Server Analysis Services似乎只允許使用字母數字,_, - 和空格。 – dgills

回答

1

如果您創建一個C#類是這樣的:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Data.SqlTypes; 
using Microsoft.SqlServer.Server; 
using System.Collections; 

namespace ExtractMdxParts 
{ 
    public partial class UserDefinedFunctions 
    { 
     public class EventData 
     { 
      public SqlString Product; 
      public SqlString CategoryFilter; 
      public SqlString Group; 
      public SqlString ExtraData; 
     } 

     [Microsoft.SqlServer.Server.SqlFunction(
     FillRowMethodName = "FillRow", 
     TableDefinition = "Product nvarchar(128), CategoryFilter nvarchar(128), Group nvarchar(128), Extradata nvarchar(MAX)", 
     IsDeterministic = true)] 

     public static IEnumerable ExtractParts([SqlFacet(MaxSize = -1)] String MdxString) 
     { 
      string[] parts = MdxString.Split(".".ToCharArray(), 4, StringSplitOptions.None); 
      if (parts.Length < 3) 
      { 
       return null; 
      } 

      List<EventData> x = new List<EventData> { }; 
      char[] trimChars = "[]".ToCharArray(); 
      EventData y = new EventData { Product = parts[0].Trim(trimChars), CategoryFilter = parts[1].Trim(trimChars), Group = parts[2].Trim(trimChars) }; 

      if (parts.Length == 4) 
      { 
       y.ExtraData = string.Join(",", parts[3].Split(".".ToCharArray()).Select(p => p.Substring(1).Trim(trimChars))); 
      } 

      x.Add(y); 

      return x; 

     } 

     public static void FillRow(object eventData, out SqlString product, out SqlString categoryFilter, out SqlString group, out SqlString extraData) 
     { 
      //I'm using here the EventData class defined above 
      EventData ed = (EventData)eventData; 
      product = new SqlString(ed.Product.ToString()); 
      categoryFilter = new SqlString(ed.CategoryFilter.ToString()); 
      group = new SqlString(ed.Group.ToString()); 
      extraData = new SqlString(ed.ExtraData.ToString()); 
     } 

    } 

} 

而且它與

use [testing] 
go 

CREATE ASSEMBLY ExtractMdxParts 
    FROM 'C:\Your\Path\Here\ExtractMdxParts.dll' 
    WITH PERMISSION_SET = EXTERNAL_ACCESS 

GO 

CREATE FUNCTION ExtractParts (@MdxString nvarchar(MAX)) 
    RETURNS TABLE (Product nvarchar(128), 
        CategoryFilter nvarchar(128), 
        [Group] nvarchar(128), 
        ExtraData nvarchar(MAX) 
        ) 
    AS EXTERNAL NAME [ExtractMdxParts].[ExtractMdxParts.UserDefinedFunctions].ExtractParts 
GO 

其中 '測試' 是你的數據庫的名稱和您添加到SQL Server所有的煩雜的位允許CLR程序...

然後你可以做的事情,如

SELECT * FROM dbo.ExtractParts(N'[a].[b].[c].&[e].&[f]') 

,並得到像

Product CategoryFilter Group ExtraData 
----------------------------------------- 
a  b    c  e,f 

重要的部分,我不得不使用,使一個表它的工作:

  • using System.Collections;這樣就可以public static IEnumerable ExtractParts...
  • new SqlString(...可能不是重要,但我越來越絕望,因爲「因爲T-SQL和CLR類型...不匹配「
  • 我沒有去簽署大會的方式,因爲VS不會讓我簽署大會,並沒有給我一個有意義的錯誤信息,所以我做了蠻力ALTER AUTHORIZATION ON DATABASE::testing TO [computername\accountname]。使用簽名:我只是寫這個作爲對這個問題的回答;你將有更多的時間在沒有鄰居抱怨的情況下喊VS.
  • 另一個可能不需要的東西是[SqlFacet(MaxSize = -1)]它出自Adam Machanic寫的something。但是,如果寫它,它很可能是一個好主意。

哦......我使用的SQL Server 2014一起選擇使用.NET 4.5.2我VS2015社區版。

我測試了它爲具有以下數據的工作:

[] [bhgshsfhsf] [chhhhhhhhhhhhhhhhhhhh]。 & [qwert]。 & [asd]。 & [tyu]。 & []。 & vbncmzxvb] [a134141]。[bhgshsfhsf]。[chhhhhhhhhhhhhhhhhhhh]。 & [qwert]。 & [asd]。 & [tyu]。 & []。 & vbncmzxvb] [a134141] [bhgshsfhsf] [chhhhhhhhhhhhhhhhhhhh] [A]。[B] [C]

它返回NULLExtraData列,如果沒有額外的數據。

如果將NULL傳遞給它,則會失敗,並且如果將空字符串傳遞給它,則會爲每個列提供一個空字符串。這對你來說可能是或者可能不是問題。

參考:Introduction to SQL Server CLR table valued functions

+0

這絕對是不可思議的,安德魯。感謝您花時間不僅爲我的*精確*用例編寫優雅的代碼,而且非常清楚地解釋如何從頭開始創建程序集並最終將其作爲用戶定義的函數實現。 +1教給我一個令人難以置信的有用的.NET功能! – dgills

+0

@dgills不客氣 - 我寫了一個CLR函數已經很長時間了。我沒有對它進行廣泛的測試,因爲它在工作時已經很晚了。另外,對於你的問題,一個更好的標題可能是「CLR函數來解析MDX字符串」 - 它可以幫助搜索人。 –

1

我能夠得到你想要的,使用你已有的東西。希望這段代碼可以幫助你。

using System.Text.RegularExpressions; 

    public Form1() 
    { 
     InitializeComponent(); 
     string linetoparse = "[Event Product].[Event Category Filter].[Category Group].&[E].&[F].&[G].&[H]"; 

     DoIt(linetoparse); 
    } 

    private void DoIt(string linetoparse) 
    { 
     string pattern = @"((?<=\[)(.*?)(?=\]))";//the pattern you are looking for 
     MatchCollection matches = null;//initialize a variable to hold your matches 

     if (Regex.IsMatch(linetoparse, pattern))//If there is at least 1 match 
     { 
      matches = Regex.Matches(linetoparse, pattern);//store the matches in our storage variable 
     } 

     if (matches != null) 
     { 
      string match1 = ((Match)matches[0]).ToString();//Event Product 
      string match2 = ((Match)matches[1]).ToString();//Event Category Filter 
      string match3 = ((Match)matches[2]).ToString();//Category Group 
     } 
    } 
+0

這是美麗的,完美的作品,謝謝! :)我們的商店有.NET應用程序運行我們的幾個進程,但是這個特定的項目是使用正則表達式彙編庫在香草T-SQL中編寫的。我最終想要使用這個。 – dgills