[英]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 ... |
+----+------------+---------+-------------------------------------------------------------------------+
分割字符串參考:
string_split()
:后續#1-Aaron Bertrand 如果您需要支持最多一百萬個字符的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.