My company has a logging table that contains a column that contains a VARCHAR(N)row that should be XML, but as it turned out, it is not always well formed. To perform log analysis (to identify error trends, etc.), I used the operator LIKE. However, this is remarkably slow.
I recently discovered that SQL Server supports XQuery, so I started playing with it. The problem that I am facing is that I cannot understand the error handling method CAST/CONVERTin my instruction SELECT. The closest I have come requires SQL Server 2012 as it has a feature TRY_CONVERT, but upgrading from 2008 R2 is not an option now.
Here's what I have (what will work if my company works in 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]
,IsMatch(@search, 'Other') as 'Error'
FROM [MyDatabase].[dbo].[Log] (NOLOCK) ) a
GROUP BY Error
Commented out CAST(or alternately a CONVERT) will result in a request error as soon as it encounters malformed XML. If I restrict TOP (N), I can guarantee that there are no errors, and the operator SELECTis incredibly fast. I just need a way to handle errors for each line.
I have considered using TRY/CATCHin IsMatch(), but this cannot be used in a function. As an alternative to use TRY/CATCH, I looked at the stored procedure, but I cannot figure out how to include it in the sentence SELECT.