PATINDEX()其中pattern在列表中

时间:2014-06-23 15:46:23

标签: sql tsql

我需要在堆栈跟踪中的分隔符的第二个实例的左侧创建所有内容的子字符串。堆栈跟踪如下所示:

在C:\ src \ Jenova \ 11.1 \中的AutoTagCore.net.windward.autotag.controls.reports.ReportHandler.LaunchReport(IDocumentInfo docInfo,RunReportParams props,RunReportVariables变量,ImportMetrics []& metrics,BaseTag& gotoTag)合并\ AutoTag \ AutoTagCore \ net \ windward \ autotag \ controls \ reports \ ReportHandler.cs:第155行,位于AutoTagCore.net.windward.autotag.controls.reports.ReportHandler.LaunchReport(IDocumentInfo docInfo,RunReportParams道具,RunReportVariables变量,BaseTag& gotoTag)等等。

在这种情况下,“at”是分隔符。但是,这些是来自全球各地的用户报告,因此“at”实际上已针对其语言进行了本地化。我可以通过调用

轻松地提取各种可能性
select distinct left(e.[StackTrace], CHARINDEX(' ',e.[StackTrace]))

由于跟踪始终以本地化的“at”

开头

我想做的是选择

之类的东西
select substring(e.stacktrace,charindex(' ',e.stacktrace), len(left(e.stacktrace, patindex('%' + IN LIST(select distinct left(e.[StackTrace], CHARINDEX(' ',e.[StackTrace]))) + ' %'    ,e.stacktrace)))) as trace

这是可能的,还是我需要为每个可能的分隔符做一些案例?

2 个答案:

答案 0 :(得分:1)

您可以使用用户定义的函数来定位第n次出现的模式。

    /*******************************************************************************
Description:    Find the Nth Occurrence of a Target string within another string.
                This function can search the string from either the left or the right -
                i.e. you can find the 3rd occurrence, the 2nd to last occurrence, etc.
                If an Nth occurrence is not found, returns zero.

Parameters:     - Input(s)
            @strTarget      - The string to search for
            @strSearched    - The string being searched
            @intOccurrence  - The specific occurrence to find:
                                Positive values search Left-to-Right, Negative values Right-to-Left

            - Output(s)
            Returns the character position of the @intOccurrence of @strTarget within @strSearched

Usage Example:
    SELECT dbo.udfCharIndex2('ow', 'how now brown cow', 3)
        returns the location of the third occurrence of 'ow' which is 11
    SELECT dbo.udfCharIndex2('ow', 'how now brown cow', -2)
        returns the location of the 2nd last occurrence of 'ow' which is 11
    SELECT dbo.udfCharIndex2('ow', 'how now brown cow', -1)
        returns the location of the last occurrence of 'ow' which is 16
    SELECT dbo.udfCharIndex2('ow', 'how now brown cow', 5)
        returns 0 since there are not 5 occurrences of 'ow'

*******************************************************************************/
CREATE FUNCTION dbo.udfCharIndex2(
    @strTarget varchar(8000), 
    @strSearched varchar(8000), 
    @intOccurrence smallint
    ) RETURNS smallint AS
BEGIN
    DECLARE @intPointer smallint, @intCounter smallint

    SELECT  @intCounter = 0,
            @intPointer = 0

    -- If Right2Left search, Reverse the Target & Searched strings
    IF @intOccurrence < 0
        SELECT @strTarget = Reverse(@strTarget),
            @strSearched = Reverse(@strSearched)

    WHILE (@intCounter < ABS(@intOccurrence))
    BEGIN
        SELECT  @intPointer = CharIndex(@strTarget, @strSearched, @intPointer + 1),
                @intCounter = @intCounter + 1

        -- If Target not found, exit loop
        IF @intPointer = 0 SET @intCounter = ABS(@intOccurrence)
    END

    -- If Right2Left search, map Pointer from reversed strings back to forward strings
    IF @intOccurrence < 0 AND @intPointer <> 0 SET @intPointer = DataLength(@strSearched) - @intPointer - DataLength(@strTarget) + 2

    RETURN(@intPointer)
END

一旦识别出分隔符,使用此功能可以搜索模式的第二次出现(分隔符)并选择其左侧的所有内容。我使用你提供的样本来测试这个函数。

DECLARE @str VARCHAR(900)
SET @str = 'at AutoTagCore.net.windward.autotag.controls.reports.ReportHandler.LaunchReport(IDocumentInfo docInfo, RunReportParams props, RunReportVariables variables, ImportMetrics[]& metrics, BaseTag& gotoTag) in C:\src\Jenova\11.1\Merge\AutoTag\AutoTagCore\net\windward\autotag\controls\reports\ReportHandler.cs:line 155 at AutoTagCore.net.windward.autotag.controls.reports.ReportHandler.LaunchReport(IDocumentInfo docInfo, RunReportParams props, RunReportVariables variables, BaseTag& gotoTag) in etc. etc.'
SELECT LEFT(@str,DBO.UDFCHARINDEX2('at ', @str, 2)-1)

您可以阅读有关用户定义函数here

的更多信息

编辑,因为您已经知道如何提取分隔符,我将分隔符'at'硬编码仅用于测试。您应该执行类似的操作来处理分隔符的变化。

SELECT LEFT(@str,(DBO.UDFCHARINDEX2(left(@str, CHARINDEX(' ', @str)), @str, 2)-1))

答案 1 :(得分:0)

我最后做的是将第一个空格字符的LEFT()定义为分隔符。然后我通过substring(e.stacktrace, charindex(' ',e.stacktrace), len(e.stacktrace) - charindex(' ',e.stacktrace)+1)

将第一个空间右边的所有内容的子字符串

由此,我做到了这一点:

left(
    substring(e.stacktrace, charindex(' ',e.stacktrace), len(e.stacktrace) - charindex(' ',e.stacktrace)+1),
    CASE 
    WHEN patindex('%  ' + left(e.[StackTrace], CHARINDEX(' ',e.[StackTrace])) + '%', substring(e.stacktrace, charindex(' ',e.stacktrace), len(e.stacktrace) - charindex(' ',e.stacktrace)+1)) > 0
    THEN patindex('%  ' + left(e.[StackTrace], CHARINDEX(' ',e.[StackTrace])) + '%', substring(e.stacktrace, charindex(' ',e.stacktrace), len(e.stacktrace) - charindex(' ',e.stacktrace)+1))
    ELSE len(substring(e.stacktrace, charindex(' ',e.stacktrace), len(e.stacktrace) - charindex(' ',e.stacktrace)+1))
    END
    )

所以这给了我第二个'[separator]'实例左边的所有内容(适合语言的分隔符,前面有两个空格字符),这是堆栈跟踪的第一个“部分”(根据给出了堆栈跟踪的定义)。它还处理堆栈跟踪没有第二部分的情况。