6
4

2 回答 2

7

您需要使用以下内容。通常需要三者的组合:

  1. patindex
  2. charindex
  3. substring

回应您上面的评论,patindex在发现案例的地方不应该是 0。patindex找到指定模式的起始位置,所以如果patindex找到这种情况,它应该返回一个 > 0 的整数。

编辑:

此外,len(string)reverse(string)特定场合派上用场。

于 2013-06-06T22:34:25.837 回答
5

将 CLR 和 .NET 项目发布到 SQL Server 后,效率极高。在过去 2 年中,在我们的 2005 SQL Server 开始在 VB.Net 中使用 CLR 项目后,我发现在 TSQL 中每次出现标量函数(我已将其替换为 .NET 版本)都显着提高了性能时间。我已经将它用于高级日期操作、格式化和解析、字符串格式化和解析、MD5 哈希生成、向量长度、字符串连接聚合函数、拆分表值函数,甚至通过共享文件夹从序列化数据表中批量加载(令人惊讶快速地)。

对于 RegEx,因为它还不存在,我只能假设它与编译的 EXE 执行相同的 REGEX 一样高效,也就是说非常快。

我将分享一个来自我的 VB.Net CLR 项目的代码文件,它允许一些 RegEx 功能。此代码将是发布到您的服务器的 .NET CLR DLL 的一部分。

功能总结

Regex_IsMatch(Data,Parttern,Options) AS tinyint (0/1 结果)

例如。SELECT dbo.Regex_IsMatch('Darren','[trwq]en$',NULL) -- 返回 1 / true

Regex_Group(data,pattern,groupname,options) as nvarchar(max) (捕获返回的组值)

例如。SELECT dbo.Regex_Group('Cable 180+e10 to 120+e3',' (?[0-9]+)+e[0-9]+','n',NULL) -- 返回 '180'

Regex_Replace(data,pattern,replacement,options) as nvarchar(max) (返回修改后的字符串)

例如。SELECT dbo.Regex_Replace('电缆 180+e10 到 120+e3',' (?[0-9]+)+e(?[0-9]+)','${e}:${n]' ,NULL) -- 返回“电缆 10:180 到 3:120”

Partial Public Class UserDefinedFunctions

    ''' <summary>
    ''' Returns 1 (true) or 0 (false) if a pattern passed is matched in the data passed.
    ''' Returns NULL if Data is NULL.
    ''' options example, full or partial names can be used after slashes or hypens with or without spaces, some are exclusive of each other "/ic /ex -s" = "\ignorecase -explicitcapture/singleline"
    ''' </summary>
    ''' <param name="data"></param>
    ''' <param name="pattern"></param>
    ''' <param name="options">options example, full or partial names can be used after slashes or hypens with or without spaces, some are exclusive of each other "/ic /ex -s" = "\ignorecase -explicitcapture/singleline"</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Microsoft.SqlServer.Server.SqlFunction()> _
    Public Shared Function Regex_IsMatch(data As SqlChars, pattern As SqlChars, options As SqlString) As SqlByte
        If pattern.IsNull Then
            Throw New Exception("Pattern Parameter in ""RegEx_IsMatch"" cannot be NULL")
        End If
        If data.IsNull Then
            Return SqlByte.Null
        Else
            Return CByte(If(Regex.IsMatch(data.Value, pattern.Value, Regex_Options(options)), 1, 0))
        End If
    End Function

    ''' <summary>
    ''' Returns the Value of a RegularExpression Pattern Group by Name or Number.
    ''' Group needs to be captured explicitly. Example Pattern "[a-z](?&lt;m&gt;[0-9][0-9][0-9][0-9])" to capture the numeric portion of an engeneering number by the group called "m".
    ''' Returns NULL if The Capture was not successful.
    ''' Returns NULL if Data is NULL.
    ''' options example, full or partial names can be used after slashes or hypens with or without spaces, some are exclusive of each other "/ic /ex -s" = "\ignorecase -explicitcapture/singleline"
    ''' </summary>
    ''' <param name="data"></param>
    ''' <param name="pattern"></param>
    ''' <param name="groupName">Name used in the explicit capture group</param>
    ''' <param name="options">options example, full or partial names can be used after slashes or hypens with or without spaces, some are exclusive of each other "/ic /ex -s" = "\ignorecase -explicitcapture/singleline"</param>
    <Microsoft.SqlServer.Server.SqlFunction()> _
    Public Shared Function Regex_Group(data As SqlChars, pattern As SqlChars, groupName As SqlString, options As SqlString) As SqlChars
        If pattern.IsNull Then
            Throw New Exception("Pattern Parameter in ""RegEx_IsMatch"" cannot be NULL")
        End If
        If groupName.IsNull Then
            Throw New Exception("GroupName Parameter in ""RegEx_IsMatch"" cannot be NULL")
        End If
        If data.IsNull Then
            Return SqlChars.Null
        Else
            Dim m As Match = Regex.Match(data.Value, pattern.Value, Regex_Options(options))
            If m.Success Then
                Dim g As Group
                If IsNumeric(groupName.Value) Then
                    g = m.Groups(CInt(groupName.Value))
                Else
                    g = m.Groups(groupName.Value)
                End If
                If g.Success Then
                    Return New SqlChars(g.Value)
                Else ' group did not return or was not found.
                    Return SqlChars.Null
                End If
            Else 'match failed.
                Return SqlChars.Null
            End If
        End If
    End Function

    ''' <summary>
    ''' Does the Equivalent toi Regex.Replace in .NET.
    ''' Replacement String Replacement Markers are done in this format "${test}" = Replaces the capturing group (?&lt;test&gt;...)
    ''' If the replacement pattern is $1 or $2 then it replaces the first or second captured group by position.
    ''' Returns NULL if Data is NULL.
    ''' options example, full or partial names can be used after slashes or hypens with or without spaces, some are exclusive of each other "/ic /ex -s" = "\ignorecase -explicitcapture/singleline"
    ''' </summary>
    ''' <param name="data"></param>
    ''' <param name="pattern"></param>
    ''' <param name="replacement">Replacement String Replacement Markers are done in this format "${test}" = Replaces the capturing group (?&lt;test&gt;...). If the replacement pattern is $1 or $2 then it replaces the first or second captured group by position.</param>
    ''' <param name="options">options example, full or partial names can be used after slashes or hypens with or without spaces, some are exclusive of each other "/ic /ex -s" = "\ignorecase -explicitcapture/singleline"</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <SqlFunction()> _
    Public Shared Function Regex_Replace(data As SqlChars, pattern As SqlChars, replacement As SqlChars, options As SqlString) As SqlChars
        If pattern.IsNull Then
            Throw New Exception("Pattern Parameter in ""Regex_Replace"" cannot be NULL")
        End If
        If replacement.IsNull Then
            Throw New Exception("Replacement Parameter in ""Regex_Replace"" cannot be NULL")
        End If
        If data.IsNull Then
            Return SqlChars.Null
        Else
            Return New SqlChars(Regex.Replace(data.Value, pattern.Value, replacement.Value, Regex_Options(options)))
        End If
    End Function

    ''' <summary>
    ''' Buffered list of options by name for speed.
    ''' </summary>
    Private Shared m_Regex_Buffered_Options As New Generic.Dictionary(Of String, RegexOptions)(StrComp)
    ''' <summary>
    ''' Default regex options used when options value is NULL or an Empty String
    ''' </summary>
    Private Shared ReadOnly m_Regex_DefaultOptions As RegexOptions = RegexOptions.IgnoreCase Or RegexOptions.ExplicitCapture Or RegexOptions.Multiline

    ''' <summary>
    ''' Get the regular expressions options to use by a passed string of data.
    ''' Formatted like command line arguments.
    ''' </summary>
    ''' <param name="options">options example, full or partial names can be used after slashes or hypens with or without spaces, some are exclusive of each other "/ic /ex -s" = "\ignorecase -explicitcapture/singleline "</param>
    Private Shared Function Regex_Options(options As SqlString) As RegexOptions
        Return Regex_Options(If(options.IsNull, "", options.Value))
    End Function

    ''' <summary>
    ''' Get the regular expressions options to use by a passed string of data.
    ''' Formatted like command line arguments.
    ''' </summary>
    ''' <param name="options">options example, full or partial names can be used after slashes or hypens with or without spaces, some are exclusive of each other "/ic /ex -s" = "\ignorecase -explicitcapture/singleline"</param>
    Private Shared Function Regex_Options(options As String) As RegexOptions
        'empty options string is considered default options.
        If options Is Nothing OrElse options = "" Then
            Return m_Regex_DefaultOptions
        Else
            Dim out As RegexOptions
            If m_Regex_Buffered_Options.TryGetValue(options, out) Then
                Return out
            Else
                'must build options and store them
                If options Like "*[/\-]n*" Then
                    out = RegexOptions.None
                End If
                If options Like "*[/\-]s*" Then
                    out = out Or RegexOptions.Singleline
                End If
                If options Like "*[/\-]m*" Then
                    out = out Or RegexOptions.Multiline
                End If
                If options Like "*[/\-]co*" Then
                    out = out Or RegexOptions.Compiled
                End If
                If options Like "*[/\-]c[ui]*" Then
                    out = out Or RegexOptions.CultureInvariant
                End If
                If options Like "*[/\-]ecma*" Then
                    out = out Or RegexOptions.ECMAScript
                End If
                If options Like "*[/\-]e[xc]*" Then
                    out = out Or RegexOptions.ExplicitCapture
                End If
                If options Like "*[/\-]i[c]*" OrElse options Like "*[/\-]ignorec*" Then
                    out = out Or RegexOptions.IgnoreCase
                End If
                If options Like "*[/\-]i[pw]*" OrElse options Like "*[/\-]ignore[pw]*" Then
                    out = out Or RegexOptions.IgnorePatternWhitespace
                End If
                If options Like "*[/\-]r[tl]*" Then
                    out = out Or RegexOptions.RightToLeft
                End If
                'store the options for next call (for speed)
                m_Regex_Buffered_Options(options) = out
                Return out
            End If
        End If
    End Function

End Class
于 2013-06-06T22:55:27.827 回答