Tsql 如何在强制转换/转换之前检查VARCHAR(n)是否有格式良好的XML

Tsql 如何在强制转换/转换之前检查VARCHAR(n)是否有格式良好的XML,tsql,validation,casting,xquery-sql,Tsql,Validation,Casting,Xquery Sql,我的公司有一个日志记录表,其中包含一个VARCHAR(N)列,其中放置了一个应该是XML的字符串,但事实证明,它并不总是格式良好的。为了对日志进行分析(识别错误趋势等),我一直在使用类似于的语句。然而,这是非常缓慢的 最近,我发现SQLServer支持XQuery,所以我开始使用它。我遇到的问题是,我无法找到一种方法来处理我的SELECT语句中的CAST/CONVERT错误。最近的版本需要SQL Server 2012,因为它有TRY\u CONVERT功能,但现在还不能从2008 R2升级 以

我的公司有一个日志记录表,其中包含一个
VARCHAR(N)
列,其中放置了一个应该是XML的字符串,但事实证明,它并不总是格式良好的。为了对日志进行分析(识别错误趋势等),我一直在使用类似于的语句。然而,这是非常缓慢的

最近,我发现SQLServer支持XQuery,所以我开始使用它。我遇到的问题是,我无法找到一种方法来处理我的
SELECT
语句中的
CAST/CONVERT
错误。最近的版本需要SQL Server 2012,因为它有
TRY\u CONVERT
功能,但现在还不能从2008 R2升级

以下是我所拥有的(如果我的公司是2012年运营的,这将起作用):

注释的
CAST
(或者是
CONVERT
)将在查询遇到格式错误的XML时立即导致查询出错。如果我限制为一个TOP(N),我可以确保没有错误,并且
SELECT
语句的运行速度非常快。我只需要一种方法来处理每行的错误


我考虑在
IsMatch()
中使用
TRY/CATCH
,但这不能在函数中使用。或者,为了使用
TRY/CATCH
,我考虑了一个存储过程,但我不知道如何将它包含在我的
SELECT
子句中。

如果您被困在2008 R2上,我想您要做的是在存储过程中使用一个只读向前游标。然后在WHILE@@FETCH\u STATUS=0循环中使用TRY-CATCH块

DECLARE logcursor CURSOR FORWARD_ONLY READ_ONLY FOR 
SELECT TOP 319 [LogId]
          ,[formattedmessage]
       FROM [GenesisLogging].[dbo].[Log] (NOLOCK)

OPEN logcursor

FETCH NEXT FROM logcursor
INTO @id, @formattedmessage

WHILE @@FETCH_STATUS = 0
BEGIN
    BEGIN TRY
    SET @xml = CONVERT(xml, @formattedmessage)
    END TRY
    BEGIN CATCH
    PRINT @id
    END CATCH; 
    FETCH NEXT FROM logcursor 
    INTO @id, @formattedmessage
END 
CLOSE logcursor;
DEALLOCATE logcursor;

你能举个例子吗?我主要是一名.Net开发人员。这使我有了我需要去的地方。我只需要将CASE逻辑传输到TRY/CATCH中,并将日志中的选择添加到temp表中。然后我在临时表上执行了计数查询,一切都很完美。非常感谢!
DECLARE logcursor CURSOR FORWARD_ONLY READ_ONLY FOR 
SELECT TOP 319 [LogId]
          ,[formattedmessage]
       FROM [GenesisLogging].[dbo].[Log] (NOLOCK)

OPEN logcursor

FETCH NEXT FROM logcursor
INTO @id, @formattedmessage

WHILE @@FETCH_STATUS = 0
BEGIN
    BEGIN TRY
    SET @xml = CONVERT(xml, @formattedmessage)
    END TRY
    BEGIN CATCH
    PRINT @id
    END CATCH; 
    FETCH NEXT FROM logcursor 
    INTO @id, @formattedmessage
END 
CLOSE logcursor;
DEALLOCATE logcursor;