簡體   English   中英

您可以從SQL中的長varchar中提取特定的文本字符串嗎?

[英]Can you extracting a specific string of text from a long varchar in SQL?

我有一個syslog服務器,它將其事件作為varchar輸入到SQL Server數據庫中。 數據看起來像這樣

Apr 27 22:03:38 ServerName MSWinEventLog 3 Application 4217 Thu Apr 27 22:03:30 2017 1009 MSExchangeHM  N/A Error ServerName 2 Microsoft Exchange Health ...

我正在嘗試計算任何唯一錯誤ID出現的次數或次數。 錯誤ID始終以“ 2017”開頭,在這種情況下,代碼為1009。我正在嘗試尋找一種對該代碼進行搜索的方法,或者在varchar的第一個“ 2017”實例之后輸出7行。

我是SQL的新手,並且有一個很好的更改,我缺少一些知識,這些知識會使這變得更容易,但是到目前為止,這是我的方法。

SELECT 
    COUNT([key]) AS CountofErrors,
    MAX(MSGTEXT) AS FULLMessage,
    CASE
       WHEN (CASE 
                WHEN LEFT(RIGHT(MSGTEXT, LEN(MSGTEXT) - 51), 12) LIKE 'a%'
                   THEN LEFT(RIGHT(MSGTEXT, LEN(MSGTEXT) - 51), 11)
                   ELSE RIGHT(LEFT(RIGHT(MSGTEXT, LEN(MSGTEXT) - 51), 12), 11) 
             END) LIKE 's%'
          THEN LEFT(LEFT(RIGHT(MSGTEXT, LEN(MSGTEXT) - 52), 12), 6)  
          ELSE (CASE
                   WHEN LEFT(RIGHT(MSGTEXT, LEN(MSGTEXT) - 51), 12) LIKE 'a%'
                      THEN LEFT(RIGHT(MSGTEXT, LEN(MSGTEXT) - 51), 11)
                      ELSE RIGHT(LEFT(RIGHT(MSGTEXT, LEN(MSGTEXT) - 51), 12), 11) 
                END) 
       END AS system2
FROM 
    SyslogDatabase
WHERE
    ...
GROUP BY
    ...

這樣可以確定事件是應用程序錯誤還是系統錯誤,因為這決定了事件ID之前還有多少個字符。 從現在開始,我會看到這變得非常混亂,因為跟隨應用程序或系統的數字可能是1到5位數字。 我希望有一個更好的方法。

在SQL Server 2016+中,您可以使用string_split()

在SQL Server 2016之前的版本中,使用Jeff Moden的CSV拆分器表值函數:

create table t (id int not null identity(1,1), msgtext varchar(8000))
insert into t values 
('Apr 27 22:03:38 ServerName MSWinEventLog 3 Application 4217 Thu Apr 27 22:03:30 
 2017 1009 MSExchangeHM  N/A Error ServerName 2 Microsoft Exchange Health ...
 2017 1009 MSExchangeHM  N/A Error ServerName 2 Microsoft Exchange Health ...
 2017 1010 MSExchangeHM  N/A Error ServerName 2 Microsoft Exchange Health ...')

select 
    t.id
  , s.ItemNumber
  , ErrorId = left(s.Item,charindex(' ',s.Item+' ')-1)
  , s.Item
from t
  cross apply dbo.delimitedsplit8k(replace(t.msgtext,'2017 ',char(30)),char(30)) s
where s.Item like '[0-9]%'

rextester 演示http ://rextester.com/LVS48443

收益:

+----+------------+---------+-------------------------------------------------------------------------+
| id | ItemNumber | ErrorId |                                  Item                                   |
+----+------------+---------+-------------------------------------------------------------------------+
|  1 |          2 |    1009 | 1009 MSExchangeHM  N/A Error ServerName 2 Microsoft Exchange Health ... |
|  1 |          3 |    1009 | 1009 MSExchangeHM  N/A Error ServerName 2 Microsoft Exchange Health ... |
|  1 |          4 |    1010 | 1010 MSExchangeHM  N/A Error ServerName 2 Microsoft Exchange Health ... |
+----+------------+---------+-------------------------------------------------------------------------+

分割字符串參考:


如果您需要支持最多一百萬個字符的varchar(max)輸入(此修改會降低性能),則可以在上面的引用中使用Aaron Bertrand的替代項(添加了ItemNumber )或其他字符串拆分選項:

create function dbo.SplitStrings_Moden (@list varchar(max), @delimiter varchar(255))
returns table with schemabinding as return
  with e1(n)        as (select 1 union all select 1 union all select 1 union all select 1 
                         union all select 1 union all select 1 union all select 1 
                         union all select 1 union all select 1 union all select 1),
       e2(n)        as (select 1 from e1 a, e1 b),
       e4(n)        as (select 1 from e2 a, e2 b),
       e42(n)       as (select 1 from e4 a, e2 b),
       ctetally(n)  as (select 0 union all select top (datalength(isnull(@list,1))) 
                         row_number() over (order by (select null)) from e42),
       ctestart(n1) as (select t.n+1 from ctetally t
                         where (substring(@list,t.n,1) = @delimiter or t.n = 0))
  select 
      ItemNumber = row_number() over(order by s.n1)
    , Item = substring(@list, s.n1, isnull(nullif(charindex(@delimiter,@list,s.n1),0)-s.n1,8000))
  from ctestart s;
go


1-讓我們首先控制捕捉算法的邏輯:

-我們需要搜索的格式“**:** 2017年”或任何當前年份。 並在相鄰的空格“ 1009”之間捕獲下一個數字

-在每個會話中使用一個數字(每天,每小時或任何會話定義)在表中插入不同的已收集錯誤代碼。
2-其次,讓我們考慮使用替代方法來簡化代碼。

-SQL游標:
首先閱讀它,並進行存儲過程和編程,以選擇每一行並對其進行字符串操作,在這種情況下,您可以進行字符串驗證和對選定文本的任何檢查,然后再確定錯誤編號(根據上一點的想法)。

-用於字符串操作的Linq Lambda:
使用.net代碼遍歷代碼,並使用.ToArray()或.ToList()收集結果。



如果我為您安排了一些示例代碼,我會盡快在此處添加,但是開始閱讀更多有關(SQL光標,Lambda表達式和字符串操作)的內容,這些內容將使您在大多數下一個任務中快速上手。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM