我有一个创建 datarequests
的应用程序,它可能非常复杂。这些需要作为表存储在数据库中。 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>
这对包含日期范围、主过滤器、系列和系列过滤器的数据请求进行编码。基本上,任何具有 index
属性的元素都可以在其父元素中多次出现 - 异常(exception)情况是 datefilter
中的 filter
。
但是这个结构有点学术性,问题更根本:
当请求通过时,像这样的 XML 将作为存储过程的参数发送到 SQLServer。此 XML 被分解为非规范化表,然后迭代写入规范化表,例如 tblDataRequest (DataRequestID PK)
、tblDataTask
、tblFilter
、 tblSeries
。这很好。
当我想将给定的 XML 定义与数据库中已有的定义相匹配时,就会出现问题。我目前通过...做到这一点
- 将 XML 分解成非规范化的表
- 使用 CTE 将数据库中的所有现有数据提取为相同的非规范化形式
- 使用巨大的
WHERE
条件进行匹配(34 行长)
..这将返回任何与给定的 XML 完全匹配的 DataRequestID。我担心这种方法最终会非常缓慢 - 部分原因是我不相信 CTE 会进行任何巧妙的过滤,它每次在应用巨大的之前都会提取所有数据哪里
。
我认为一定有更好的解决方案来解决这个问题
- 在存储
datarequest
时,还以某种方式存储datarequest 的散列并简单地匹配它。在发生碰撞的情况下,使用当前方法。但是我想使用 set-logic 来做到这一点。而且,我担心 XML 中不相关的小差异会更改哈希 - 虚假空格等。 - 以某种方式从下往上迭代执行匹配。例如,生成在最低级别上匹配的过滤器列表。将其用作
IN
的一部分以匹配 Series。将其用作IN
的一部分以匹配 DataTasks 等。问题是,当我考虑这个问题太久时,我就开始昏迷了。
基本上 - 以前有没有人遇到过这种问题(他们一定遇到过)。解决它的推荐路线是什么? 示例(伪)代码会很棒 :)
最佳答案
为了消除微小差异的可能性,我将通过 XML 转换 (XSLT) 运行请求。
或者,由于您已经有了将其解析为非规范化暂存表的代码,这也很好。然后我会简单地使用 FOR XML创建一个新的 XML 文档。
您的目标是创建一个标准化的 XML 文档,该文档在适当的地方遵守顺序并消除不一致的地方。
完成后,将其存储在新表中。现在,您可以将“标准化”请求 XML 与现有数据进行直接比较。
要进行实际比较,您可以使用散列,将 XML 存储为字符串并进行直接字符串比较,或者像这样进行完整的 XML 比较:http://beyondrelational.com/modules/2/blogs/28/posts/10317/xquery-lab-36-writing-a-tsql-function-to-compare-two-xml-values-part-2.aspx
只要 XML 永远不会超过 8000 字节,我的偏好是创建一个唯一字符串(如果您有特殊字符支持,则可以是 VARCHAR(8000) 或 NVARCHAR(4000))并在该列上创建一个唯一索引。
关于sql - 将嵌套 XML 数据与数据库表结构进行匹配的最快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12674327/