T-SQL:当长度> VarChar(MAX)时,如何比较XML类型的两个变量?

Sco*_*Bai 6 xml t-sql sql-server comparison

仅使用SQL Server 2008 R2(这将在存储过程中),如何确定XML类型的两个变量是否相同?

这是我想要做的:

DECLARE @XmlA   XML
DECLARE @XmlB   XML

SET @XmlA = '[Really long Xml value]'
SET @XmlB = '[Really long Xml value]'

IF @XmlA = @XmlB
    SELECT 'Matching Xml!'
Run Code Online (Sandbox Code Playgroud)

但是你可能知道,它会返回:

消息305,级别16,状态1,行7除非使用IS NULL运算符,否则无法比较或排序XML数据类型.

我可以转换VarChar(MAX)和比较,但这只比较前2MB.还有另外一种方法吗?

Ole*_*Dok 0

您可以将字段转换为 varbinary(max),对它们进行散列并比较散列。但是您肯定会错过 XML 是否等效但不相同的情况

要计算哈希值,您可以使用以下任一 CLR 函数:

using System;
using System.Data.SqlTypes;
using System.IO;

namespace ClrHelpers
{
    public partial class UserDefinedFunctions {
        [Microsoft.SqlServer.Server.SqlFunction]
        public static Guid HashMD5(SqlBytes data) {
            System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
            md5.Initialize();
            int len = 0;
            byte[] b = new byte[8192];
            Stream s = data.Stream;
            do {
                len = s.Read(b, 0, 8192);
                md5.TransformBlock(b, 0, len, b, 0);
            } while(len > 0);
            md5.TransformFinalBlock(b, 0, 0);
            Guid g = new Guid(md5.Hash);
            return g;
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

或者sql函数:

CREATE FUNCTION dbo.GetMyLongHash(@data VARBINARY(MAX))
RETURNS VARBINARY(MAX)
WITH RETURNS NULL ON NULL INPUT
AS
BEGIN
    DECLARE @res VARBINARY(MAX) = 0x
    DECLARE @position INT = 1, @len INT = DATALENGTH(@data)

    WHILE 1 = 1
    BEGIN
        SET @res = @res + HASHBYTES('MD5', SUBSTRING(@data, @position, 8000))
        SET @position = @position+8000
        IF @Position > @len 
          BREAK
    END
    WHILE DATALENGTH(@res) > 16 SET @res= dbo.GetMyLongHash(@res)
    RETURN @res
END
Run Code Online (Sandbox Code Playgroud)