【问题标题】:Normalising XML in SQLServer for hashing在 SQLServer 中规范化 XML 以进行散列
【发布时间】:2012-09-23 05:17:11
【问题描述】:

我问了this question,这导致我做了以下事情。

  • 创建 C# 对象结构的 XML 表示,以便将其传递给 SQLServer。
  • 创建一个存储过程,对 XML 进行哈希处理,然后将 XML 分解到相关表中,并将哈希值存储在根表中以便快速查找。

这意味着我可以将复杂的对象数据传递给 SQLServer 并在哈希上进行查找,而不是尝试分解 XML 并将其与表进行匹配(我也可以这样做,但速度很慢(呃))...

然而 - 关于 XML 的好处之一是您可以格式化它,例如缩进等 - 而且 - 属性顺序并不重要。但是当你散列一些东西时,格式和缩进很重要。所以我在 C# 中所做的是......

  • 通过将所有属性按字母顺序排列来规范化 XML
  • 使用 .ToString(DisableFormatting) 删除多余的格式化空格

这很好用,但是当我在测试时,将 格式化 XML 变得更容易,这样我就可以更容易地看到我传递给存储过程的内容。

如果可以信任 SQLServer 来保留属性顺序,那就太好了but it can't...

不保留 XML 实例中属性的顺序。当你 查询xml类型列中存储的xml实例,顺序为 生成的 XML 中的属性可能与原始 XML 不同 实例。

这意味着我不能使用 SQLServer 的 XML 数据类型来规范化数据。

困扰我的是,在某些时候有人会使用我的 proc 并认为“哦,太好了,XML,属性顺序无关紧要,格式无关紧要,表示的数据是相同的" 但是,当我散列时,情况并非如此。

有人有解决这个问题的办法吗?我真的不想在 T-SQL 中编写 XML 解析器!或者使用其他人编写的 XML 解析器来规范化它。为什么 SQLServer XML 数据类型不能只保留属性顺序?

我想我可以“信任”我的应用程序始终以相同的格式/顺序传递 XML,从而为同一对象产生相同的哈希值。但是我对存储过程也必须“信任”应用程序才能做到这一点的想法感到不舒服。我希望能够以某种方式检查 XML 的规范化,这样显然会更加健壮。

【问题讨论】:

  • 虽然 SQL Server 解析/规范化过程的结果可能不会创建与 c# 完全相同的 XML,但至少是一致的。在散列之前你不能依靠这种一致性来处理你的 XML 吗?
  • @paul 好吧,我的实际应用目的是的。但是,如果有人想查看是否存在特定记录并且他们手动调用 proc,或者从另一个应用程序使用一些 formatted XML,那么他们可能会认为它实际上不存在,然后我最终可能会得到两个语义相同但哈希值不同的记录——我想避免这种情况。

标签: .net xml tsql sql-server-2005 xml-parsing


【解决方案1】:

我将尝试序列化存储过程中的对象。

让我们假设以下类:

class MyCustomObject 
{
    int id;
    string SomeField;
}

然后您可以使用存储过程,在其中序列化 xml 中的对象并计算输入参数的校验和,然后在另一个中您可以传递 HashValue(checksum) 和 Xml。通过反序列化Xml,你可以计算Xml中字段的校验和,并与传递的HashValue进行比较。

试试这个代码: (请注意,您应该存储哈希值并将其返回给调用者并使用 xml 做一些事情)

CREATE PROCEDURE HashObject(@id int, @SomeField varchar(255)) AS
BEGIN
    SELECT
        CHECKSUM(@id, @SomeField) AS CalculatedHashValue,
        (SELECT @id AS ID, @SomeField AS SomeField FOR XML RAW('xmlRowName')) AS Xml_Data,
        @id AS SPCall_ID,
        @SomeField AS SPCall_SomeField
END
GO

CREATE PROCEDURE CheckHash(@HashValue INT, @data XML) AS
BEGIN
    SELECT  
        CHECKSUM(rt.value('@ID', 'int'), rt.value('@SomeField', 'varchar(255)')) AS Xml_CalculatedHashValue,
        @data Xml_Data,
        rt.value('@ID', 'int') AS Xml_ID,
        rt.value('@SomeField', 'varchar(255)') AS Xml_SomeField,
        @HashValue AS SPCall_HashValue

    FROM @data.nodes('xmlRowName') AS nd(rt)

END
GO

DECLARE @id INT = 11
DECLARE @SomeField varchar(255) = 'string value'
DECLARE @data XML

EXEC dbo.HashObject @id, @SomeField

SET @data = (SELECT @id AS ID, @SomeField AS SomeField FOR XML RAW('xmlRowName'))
EXEC dbo.CheckHash 0, @data

SET @data = (SELECT 25 AS ID, 'diferent string value' AS SomeField FOR XML RAW('xmlRowName'))
EXEC dbo.CheckHash 0, @data
GO  

【讨论】:

  • 感谢您的回答。我不确定如何将此解决方案应用于我的情况(请参阅this question) - 我可以让我的内部元素重复任意次数。我需要将 .Net 中的数据作为 XML 传递到 SQLServer,但我希望属性顺序和格式与哈希值无关。
猜你喜欢
  • 2014-10-04
  • 2016-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-16
  • 2013-08-13
  • 2013-03-08
相关资源
最近更新 更多