Sql 根据数据库表结构匹配嵌套XML数据的最快方法
我有一个创建Sql 根据数据库表结构匹配嵌套XML数据的最快方法,sql,sql-server-2005,data-structures,orm,Sql,Sql Server 2005,Data Structures,Orm,我有一个创建数据请求的应用程序,它可能非常复杂。这些需要作为表存储在数据库中。datarequest(作为XML)的概要是 <datarequest> <datatask view="vw_ContractData" db="reporting" index="1"> <datefilter modifier="w0"> <filter index="1" datatype="d" column="Contract Date" p
数据请求的应用程序,它可能非常复杂。这些需要作为表存储在数据库中。datarequest
(作为XML)的概要是
<datarequest>
<datatask view="vw_ContractData" db="reporting" index="1">
<datefilter modifier="w0">
<filter index="1" datatype="d" column="Contract Date" param1="2009-10-19 12:00:00" param2="2012-09-27 12:00:00" daterange="" operation="Between" />
</datefilter>
<filters>
<alternation index="1">
<filter index="1" datatype="t" column="Department" param1="Stock" param2="" operation="Equals" />
</alternation>
<alternation index="2">
<filter index="1" datatype="t" column="Department" param1="HR" param2="" operation="Equals" />
</alternation>
</filters>
<series column="Turnaround" aggregate="avg" split="0" splitfield="" index="1">
<filters />
</series>
<series column="Requested 3" aggregate="avg" split="0" splitfield="" index="2">
<filters>
<alternation index="1">
<filter index="1" datatype="t" column="Worker" param1="Malcom" param2="" operation="Equals" />
</alternation>
</filters>
</series>
<series column="Requested 2" aggregate="avg" split="0" splitfield="" index="3">
<filters />
</series>
<series column="Reqested" aggregate="avg" split="0" splitfield="" index="4">
<filters />
</series>
</datatask>
</datarequest>
这将对数据请求进行编码,该数据请求包括日期范围、主筛选器、系列和系列筛选器。基本上,任何具有索引
属性的元素都可以在其父元素中多次出现-例外情况是日期过滤器中的过滤器
但这种结构是学术性的,问题更为根本:
当请求通过时,像这样的XML将作为存储过程的参数发送到SQLServer。该XML被分解成一个非规范化的表,然后迭代地写入规范化的表,如tblDataRequest(DataRequestID PK)
,tblDataTask
,tblFilter
,tblSeries
。这很好
当我想将给定的XML定义与数据库中已有的定义进行匹配时,就会出现问题。我现在是通过
- 将XML分解到非规范化的表中
- 使用CTE将数据库中的所有现有数据拉入相同的非标准化形式
- 使用巨大的
WHERE
条件进行匹配(34行长)
…这将返回与给定XML完全匹配的任何DataRequestID。我担心这种方法最终会慢得令人痛苦——部分原因是我不相信CTE会做任何巧妙的过滤,它会在应用巨大的WHERE
之前每次都提取所有数据
我认为一定有更好的解决办法
- 在存储
数据请求时
,还要以某种方式存储数据请求的散列,并简单地匹配该散列。如果发生碰撞,请使用当前方法。然而,我想使用集合逻辑来实现这一点。此外,我还担心XML中不相关的小差异会改变散列-伪空间等
- 以某种方式从下到上迭代执行匹配。例如,生成一个在最低级别匹配的过滤器列表。将其作为
中的的一部分来匹配序列。将此作为
中的的一部分,以匹配数据任务等。问题是,当我想得太久时,我开始昏厥
基本上-以前是否有人遇到过此类问题(他们一定遇到过)。那么,解决这个问题的推荐方法是什么呢?示例(伪)代码会很好:)为了消除微小差异的可能性,我将通过XML转换(XSLT)运行请求
或者,因为您已经有了将其解析为非规范化的staging表的代码,这也很好。然后,我将简单地使用创建一个新的XML文档
这里的目标是创建一个标准化的XML文档,在适当的地方尊重顺序,并在不一致的地方消除不一致性
完成后,将其存储在新表中。现在,您可以运行“标准化”请求XML与现有数据的直接比较
要进行实际比较,可以使用散列,将XML存储为字符串并进行直接字符串比较,或者进行如下完整的XML比较:
只要XML不超过8000字节,我的首选方法是创建一个唯一的字符串(如果您有特殊的字符支持,可以是VARCHAR(8000)或NVARCHAR(4000)),并在列上创建一个唯一的索引。我使用XML规范化(修剪和排序节点)和哈希处理类似的问题。它运行得很好,速度也很快。所以它首先解析XML,应用规范化,然后以一般方式计算哈希。@ViktorStolbin感谢您的评论。所以我还有希望!我不需要对节点进行排序,因为顺序很重要——尽管属性顺序并不重要。您对属性顺序进行了排序吗?我对所有内容进行了排序,因为XML是DB查询的直观表示,我依赖于DB查询优化。可能散列实现应该对元素顺序敏感。显然,SQLServer XML类型在作为VARCHAR
传递到存储过程之前,我可能需要在应用程序端对XML进行排序。+1非常好的答案Rai!欢迎来到SO。顺便说一句,这个方法就是我如何解决这个问题的!