我的公司有一个记录表,其中包含一个VARCHAR(N)
列,其中放置了一个应该是 XML 的字符串,但事实证明它并不总是格式正确的。为了对日志进行分析(以识别错误趋势等),我一直在使用一个LIKE
语句。然而,这非常缓慢。
最近,我发现 SQL Server 支持 XQuery,所以我开始使用它。我遇到的问题是我无法找到一种方法来处理CAST/CONVERT
我的SELECT
陈述中的错误。我最接近的需要 SQL Server 2012,因为它具有该TRY_CONVERT
功能,但现在不能从 2008 R2 升级。
这是我所拥有的(如果我的公司在 2012 年运行,这将起作用):
CREATE FUNCTION IsMatch(
@message AS VARCHAR(MAX),
@match AS VARCHAR(MAX),
@default AS VARCHAR(MAX))
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE @xml XML = TRY_CONVERT(XML, @message)
DECLARE @result VARCHAR(MAX) =
CASE WHEN @xml IS NOT NULL
THEN CASE WHEN @xml.exist('(/FormattedMessage)[contains(.,sql:variable("@match"))]') = 1
THEN @match
ELSE @default
END
ELSE CASE WHEN @message LIKE '%' + @match + '%'
THEN @match
ELSE @default
END
END
RETURN @result
END
GO
DECLARE @search VARCHAR(MAX) = 'a substring of my xml error message'
SELECT Error, COUNT(*) as 'Count'
FROM ( SELECT TOP 319 [LogID]
,[Severity]
,[Title]
,[Timestamp]
,[MachineName]
,[FormattedMessage]
--,CAST([formattedmessage] as xml)
,IsMatch(@search, 'Other') as 'Error'
FROM [MyDatabase].[dbo].[Log] (NOLOCK) ) a
GROUP BY Error
一旦遇到格式错误的 XML ,注释的CAST
(或替代的 a )将导致查询出错。CONVERT
如果我限制为 TOP (N),我可以确保没有错误并且SELECT
语句运行得非常快。我只需要一种方法来逐行处理错误。
我考虑过使用TRY/CATCH
in IsMatch()
,但不能在函数中使用。或者,要使用TRY/CATCH
,我考虑了一个存储过程,但我不知道如何将它包含在我的SELECT
子句中。