[英]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.