2016-08-10 42 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