过滤 XML — 方括号谓词与 exist() 的两套过滤体系¶
这一章讲什么: 已经会拆 XML(第 4 章)之后,下一步是「只拆符合条件的那些」。 书里给了十一个配方,但骨架其实只有两根:WHERE 里的 exist() 方法,和钻进 nodes() 内部的方括号谓词。剩下的九个配方,全是 T-SQL 老兵熟悉的东西 (IN、BETWEEN、LIKE、NOT、IS NULL)在 XQuery 里的「翻译表」——以及几条 翻译过来才发现不对等的规矩。
1. 先看现象:一个具体需求,两套写法¶
本章主线例子: Person.Person 表约 19,972 行1,每行的 Demographics 列存着个人调查 XML(根元素 <IndividualSurvey>,下面平铺最多 13 个子元素:年收入 YearlyIncome、累计消费 TotalPurchaseYTD、职业 Occupation、通勤距离 CommuteDistance、首次购买日期 DateFirstPurchase…)2。
需求:「找出累计消费超过 9000 美元的人」。这个需求有两种写法,本章就围绕它们展开:
-- 写法一:exist() 在 WHERE 里筛行
WHERE Demographics.exist('IndividualSurvey[TotalPurchaseYTD > 9000]') = 1
-- 写法二:谓词钻进 nodes(),边拆边筛
CROSS APPLY Demographics.nodes('IndividualSurvey[TotalPurchaseYTD > 9000]') AS dmg(ref)
写法一只回答「要不要这行」;写法二还顺手把拆好的行集递出来。什么时候用哪个,是本章第一个要建立的判断力。
2. 顶层全景:过滤机制的翻译表¶
T-SQL 习惯 XQuery 实际写法 配方
──────────────────────────────────────────────────────────
WHERE 列 = 值 exist('路径[条件]') = 1 6-1/6-2
比较运算符 eq/ne/gt/lt/ge/le(值比较)或 =/!=/>…(通用) 6-2
IN (列表) = (值1, 值2, 值3) 6-6
BETWEEN >= 值 and <= 值 6-8
LIKE '%x%' fn:contains(元素, "x") 6-7
NOT / NOT IN != / ne / fn:not(…) 6-10
IS [NOT] NULL fn:not(fn:empty(…)) 6-11
参数传进来 sql:variable("@变量") 6-5
全文找某元素 //元素名 6-3
图说:左列是你脑子里已有的,T-SQL 的;右列是 XQuery 的——多数长得像,但规矩不同。
3. 核心原理¶
3.1 exist():三值逻辑,以及它和 WHERE 的天然搭配¶
解决什么问题: 只想按 XML 内容筛行,SELECT 里根本不需要碰 XML。
怎么做: WHERE 列.exist('XQuery表达式') = 1。表达式命中任意节点返 1,没命中返 0,XML 本身是 NULL 或传入 NULL 表达式则返 NULL——三值逻辑,和 T-SQL 的 NULL 语义对齐3。查「有没有 YearlyIncome 元素」:exist('IndividualSurvey/YearlyIncome');查「有没有 currency 属性」:路径里带 @currency——XQuery 里元素和属性的分野就是一个 @4。
为什么有效: 它返回的是 bit(1/0/NULL),直接就是 WHERE 能吃的东西;引擎在扫行时逐份文档求值,不合条件的行连拆都不用拆。
边界: exist() 是「筛行」工具,不出数据——要数据还得 value()/nodes()。
3.2 方括号谓词:写进路径里的 WHERE¶
解决什么问题: 拆(nodes)的同时只想拆符合条件的节点。
怎么做: 在路径的某一级后面挂 [条件],条件引用该级元素的子孙:
IndividualSurvey[TotalPurchaseYTD > 9000]
└─┬─┘ └──────────────┬──────────────┘
父元素 方括号谓词:对 IndividualSurvey 的每个实例求值
注意一个容易写错的地方:谓词里引用子元素时不带路径前缀——TotalPurchaseYTD 不是 /IndividualSurvey/TotalPurchaseYTD。书里的解释:这一步是隐含的5。
为什么有效: 谓词在拆分之前求值,不符合的节点根本不进行集——这就是章末性能优势的来源(见 3.11)。
3.3 运算符与类型:XQuery 比 T-SQL 挑剔得多¶
比较运算符两套。 XQuery 有两套比较:通用比较(=、!=、>、<、>=、<=,允许和序列比)和值比较(eq、ne、gt、lt、ge、le,只比单值)——写 exist/谓词用哪套都行,行为多数时候一致6。T-SQL 里没有对应物的是节点比较:<<(左节点在文档序中先于右节点)、>>(后于)、is(两个引用是否同一个节点)——「文档序」就是 XML 里节点出现的先后顺序,它是节点比较的基准7。书里给了一个具体例子:比较 <Education> 和 <Occupation> 谁在前,用 value('(/IndividualSurvey/Education)[1] << (/IndividualSurvey/Occupation)[1]', 'nvarchar(20)') 得 true,因为 Education 在文档里先出现8。
类型不隐式转换——本章最容易踩的雷。 T-SQL 会替你隐式转类型(字符串和数字比,悄悄转了);XQuery 不转,比不动就报错。具体规矩9:
| 值的样子 | 写法 | 例子 |
|---|---|---|
| 数字 | 不加引号 | TotalPurchaseYTD > 9000 |
| 字符串 | 双引号 | Occupation = "Manual" |
| 日期/时间 | 构造函数 | DateFirstPurchase = xs:date("2002-06-28Z") |
把 9000 写成 "9000"(字符串),立刻报错——因为 TotalPurchaseYTD 是数字,字符串和数字不可比10。日期例外地「自动处理转换」,但正规范式是 xs:date() / xs:time() / xs:dateTime() 三个构造函数;Z 表示零经线(UTC+00:00),带不带等价11。
运算符也全小写: and、or 大写报错——和第 04 章方法名全小写同一条军规12。
3.4 //:全文找元素,以及它的性能代价¶
解决什么问题: 元素埋在很深的层级,而且路径不固定,想「不管在哪,全部找出来」。
怎么做: 路径开头或中间用 //,它是 /descendant-or-self::node()/ 的速写——「从当前节点往下所有层级」。书里的例子:在简历 XML 里捞所有电话号码(Resume.nodes('//ns:Tel.Number')),不管它挂在哪个地址下面13。
边界: 书里给了明确警告:// 让引擎全文搜索,可能造成性能问题,用之前要测——第 07 章会展开 nodes() 的性能优化14。
3.5 sql:variable():把 T-SQL 参数送进谓词¶
解决什么问题: 过滤条件来自存储过程参数或变量(「按用户传入的收入区间查」),而 XML DML/XQuery 自己碰不到 T-SQL 变量。
怎么做: nodes('IndividualSurvey[YearlyIncome = sql:variable("@YearlyIncome")]')。它把 T-SQL 变量映射进 XQuery 表达式,存进存储过程参数里尤其顺15。两个语法形态:比元素 [子元素 运算符 sql:variable("@var")]、比属性 [@属性 运算符 sql:variable("@var")]16。
大小写规矩(又一条军规): 函数名 sql:variable() 必须全小写,大写报 Msg 2395;但变量名本身不区分大小写17。
为什么有效: 参数化之后,存储过程可以反复执行不同值(书里连跑五档收入区间:0-25000、25001-50000、…、greater than 100000)18,而且避免拼接字符串(也就不怕注入)。
3.6 列表、范围、多条件:翻译表的主体¶
IN 列表 → = (序列)。 T-SQL 的 IN ('a','b','c'),XQuery 写成 = ("Clerical","Manual","Professional")——等号加括号列表。书里点破:最常见的错误就是照搬 IN 语法;其实 = 碰上序列,语义本来就是「等于其中任意一个」19。
BETWEEN → >= and <=。 XQuery 没有 BETWEEN,两个谓词用 and 连起来,功能完全等价20。
LIKE '%x%' → fn:contains(元素, "x")。 fn:contains() 两个参数:被检元素、字符串模式;返回布尔。行为上等于被通配符包围的 LIKE('%x%')21。两个缺口:fn:starts-with() 和 fn:ends-with() SQL Server 不支持——需要前缀/后缀匹配时,书里的解法是混合方案:先用 fn:contains 粗筛(XQuery 内),拆出来后用 T-SQL 的 LIKE 'Manual%' 精筛(WHERE 里)——各干各擅长的22。
多条件 → and/or 组合。 一个谓词里随便连,比如「消费在 1001–1004 之间、且通勤 0-1 英里、或首次购买晚于 2004-07-30」:[TotalPurchaseYTD >= 1001 and TotalPurchaseYTD <= 1004 and CommuteDistance = "0-1 Miles" or DateFirstPurchase > xs:date("2004-07-30")]23。注意这里 and/or 没有括号时的优先级——和 T-SQL 一样 and 优先(补充说明,不在书里明写,依运算符语义)。
3.7 否定与空值:!=、ne、fn:not()、fn:empty()¶
否定三件套24:
| 场景 | 写法 |
|---|---|
| 单值不等 | != "0-25000" 或值比较 ne "0-25000" |
| 不在列表里 | fn:not(Occupation = ("Clerical","Manual","Professional")) |
| 区间/复合否定 | 外层包 fn:not(...) |
空值检测。 T-SQL 的 IS NULL/IS NOT NULL,XQuery 里用 fn:empty()(判空序列)加 fn:not() 组合:fn:not(fn:empty(Occupation)) = 「Occupation 有值」25。为什么不用 exist()?exist() 在 nodes() 的谓词里不受支持——fn:empty/fn:not 就是谓词内部的替代品,书里明说它俩「类似 T-SQL 的 IS NULL 和 IS NOT NULL」26。
顺带一个实测对比: 同样 7652 行结果,fn:empty() 方案 CPU 454 毫秒/总耗时 496 毫秒;exist() 方案 CPU 485 毫秒/总耗时 577 毫秒——fn:empty() 略快,但「你的机器上数字会不一样」27。
3.8 本章的结论:过滤要放在 XQuery 里,不要放在 WHERE 里¶
解决什么问题: 很多人图省事,先把 XML 全拆了再用 T-SQL WHERE 过滤。
怎么做(对照实验): 书里用 SET STATISTICS TIME ON 跑同一需求两种写法——nodes() 谓词过滤 vs 拆完全量再 WHERE ref.value(...) = 'Manual'。结果:2384 行,XQuery 过滤比 WHERE 过滤快一倍以上28。
为什么有效: 谓词在拆分之前生效——不符合的节点不产出行;WHERE 是拆分之后过滤——每一行都已经付过拆分的成本。前者是「进门时查票」,后者是「放所有人进场再清场」。
作者的明确结论: 「XQuery filtering should be your first choice」28。但书末也留了余地:T-SQL WHERE 的过滤机制更全面,XQuery 谓词够用但表达能力有边界(比如复杂的跨行条件、函数计算)——这是权衡,不是铁律29。
4. 作者的判断与证据¶
有计时实验支撑的: fn:empty() vs exist() 的毫秒对比27;XQuery 谓词 vs WHERE 过滤的两倍以上差距28。样本是 2 万行的真实列,虽然单库单机,方向性结论可靠,绝对数字不可移植——书里自己也注明「你的机器数字会不同」。
作者的经验判断: 「最常见的误解就是图省事用 T-SQL WHERE 过滤 XML」28;「IN 语法照搬是最高频的错误」19;「// 要用前先测」14。这些都有演示支撑,属于「经验 + 当场验证」型论断。
需要补充的: 谓词过滤快一倍的前提是过滤条件能写进 XQuery;一旦条件是「和别的表关联」「对拆出的值做 T-SQL 函数运算」,WHERE 不可避免——本章的「first choice」应读作「能进谓词就进谓词」(补充判断,不在书里)。
5. 边界与局限¶
- 谓词里能用的函数有限:SQL Server 的 XQuery 是子集,fn:starts-with/ends-with 缺席就是明证22;更复杂的模式匹配(正则)没有。
- exist() 和谓词都绕不过命名空间:WITH XMLNAMESPACES 或内部 declare,和第 04/05 章同一套规矩,本章配方一律用 DEFAULT 声明简化。
- 性能数字全部来自单机样例库(约 2 万行),大表上的差距形态可能不同(补充判断,不在书里)。
- WHERE vs 谓词的对比只测了一个条件,多条件、带索引的场景书中未展开——第 07 章(XML 索引)才是这块的正主。
6. 可带走的¶
本章主线例子,一行走完: 2 万行个人调查 XML → exist() 筛「有 YearlyIncome 的」(三值逻辑)→ 谓词 [TotalPurchaseYTD > 9000] 边拆边筛(数字不加引号)→ 参数化走 sql:variable() → 列表 (a,b,c)、区间 >= and <=、模糊 fn:contains()、否定 fn:not()、空值 fn:empty() → 计时对比:XQuery 谓词比 T-SQL WHERE 快一倍以上。
- 两套过滤工具: exist() 在 WHERE 筛行(返回 1/0/NULL),谓词
路径[条件]在 nodes() 里边拆边筛3。 - 谓词里子元素不带路径前缀,这一步隐含5。
- 类型不隐式转换: 数字裸写、字符串双引号、日期
xs:date();写错类型直接报错910。 - IN →
= (列表);BETWEEN →>= and <=;LIKE '%x%' → fn:contains();NOT IN → fn:not(= 列表)19202124。 and/or/sql:variable()全小写;变量名本身不挑大小写1217。//全文找元素,用前先测性能14。- exist() 不能用在 nodes() 谓词里;判空用
fn:not(fn:empty(…))26。 - fn:starts-with/ends-with 不被支持;要前后缀匹配用「XQuery 粗筛 + T-SQL LIKE 精筛」混合方案22。
- 过滤尽量放进 XQuery 谓词(拆前),别拆完再用 WHERE(拆后)——实测快一倍以上28。
- 样例规模:Person.Person 约 19,972 行,数字来自本章注释1。
7. 原文地图¶
| 主题 | 原书章 | 原文位置 |
|---|---|---|
| exist() 三值逻辑 | Chapter 6: Filtering XML | text/10-ch06-chapter-6-filtering-xml.txt:93(搜「TRUE (a bit value」) |
| 属性检测的 @ 语法 | 同上 | text/10-ch06-chapter-6-filtering-xml.txt:131(搜「to match attributes」) |
| 谓词结构与隐含步 | 同上 | text/10-ch06-chapter-6-filtering-xml.txt:201(搜「square brackets」) · text/10-ch06-chapter-6-filtering-xml.txt:219(搜「implied」) |
| 比较运算符表与节点比较 | 同上 | text/10-ch06-chapter-6-filtering-xml.txt:221(搜「comparison operators」) · text/10-ch06-chapter-6-filtering-xml.txt:236(搜「Document order」) |
| 类型转换错误与日期 | 同上 | text/10-ch06-chapter-6-filtering-xml.txt:262(搜「implicit conversion」) · text/10-ch06-chapter-6-filtering-xml.txt:303(搜「xs:date()」) |
| // 全文查找 | 同上 | text/10-ch06-chapter-6-filtering-xml.txt:320(搜「double forward slashes」) |
| // 的性能警告 | 同上 | text/10-ch06-chapter-6-filtering-xml.txt:387(搜「performance problems」) |
| sql:variable() 与大小写 | 同上 | text/10-ch06-chapter-6-filtering-xml.txt:444(搜「access the values」) · text/10-ch06-chapter-6-filtering-xml.txt:506(搜「Msg 2395」) |
| 序列模拟 IN | 同上 | text/10-ch06-chapter-6-filtering-xml.txt:540(搜「not intuitive」) |
| fn:contains 与混合方案 | 同上 | text/10-ch06-chapter-6-filtering-xml.txt:577(搜「two arguments」) · text/10-ch06-chapter-6-filtering-xml.txt:588(搜「does not support」) |
| 范围与多条件 | 同上 | text/10-ch06-chapter-6-filtering-xml.txt:652(搜「same functionality as the BEWTEEN」) · text/10-ch06-chapter-6-filtering-xml.txt:694(搜「four predicates」) |
| 否定三件套 | 同上 | text/10-ch06-chapter-6-filtering-xml.txt:744(搜「three negative operators」) |
| fn:empty 与 exist 的对比 | 同上 | text/10-ch06-chapter-6-filtering-xml.txt:783(搜「alternative to the exist」) · text/10-ch06-chapter-6-filtering-xml.txt:821(搜「advantage over the exist」) |
| WHERE vs XQuery 计时 | 同上 | text/10-ch06-chapter-6-filtering-xml.txt:844(搜「inefficient solution」) · text/10-ch06-chapter-6-filtering-xml.txt:903(搜「more than twice」) |
| 样例规模 | 同上 | text/10-ch06-chapter-6-filtering-xml.txt:706(搜「19,972 rows」) |
-
出处:「Chapter 6: Filtering XML」第 705–706 段(
text/10-ch06-chapter-6-filtering-xml.txt:706,搜「19,972 rows」)。原文:「For demo purposes, the table Person.Person and the column Demographics, containing 19,972 rows, have been selected for this chapter」。 ↩↩ -
出处:「Chapter 6: Filtering XML」第 107–113 段(
text/10-ch06-chapter-6-filtering-xml.txt:107,搜「IndividualSurvey」)。原文:「The root element is IndividualSurvey, and it can contain up to 13 child elements」。 ↩ -
出处:「Chapter 6: Filtering XML」第 90–98 段(
text/10-ch06-chapter-6-filtering-xml.txt:93,搜「TRUE (a bit value」)。原文:「TRUE (a bit value of 1), when the XQuery expression returns a nonempty result」「FALSE (a bit value of 0)…empty result」「NULL, when a NULL is passed in as the XQuery expression or the XML instance is NULL」。 ↩↩ -
出处:「Chapter 6: Filtering XML」第 130–157 段(
text/10-ch06-chapter-6-filtering-xml.txt:131,搜「to match attributes」)。原文:「To detect the attributes you need to provide an XPath to the attribute」,示例@survey.exist('IndividualSurvey/YearlyIncome/@currency')。 ↩ -
出处:「Chapter 6: Filtering XML」第 199–220 段(
text/10-ch06-chapter-6-filtering-xml.txt:201,搜「square brackets」)与第 217–220 段(text/10-ch06-chapter-6-filtering-xml.txt:219,搜「implied」)。原文:「The XML filters specify a Boolean expression…surrounded by square brackets」;注释说明实际步被隐含(the step is implied)。 ↩↩ -
出处:「Chapter 6: Filtering XML」第 221–235 段(
text/10-ch06-chapter-6-filtering-xml.txt:223,搜「comparison operators」)。表 6-1 列出 =/eq、!=/ne、>/gt、</lt、>=/ge、<=/le 及 <<、>>、is。 ↩ -
出处:「Chapter 6: Filtering XML」第 236–244 段(
text/10-ch06-chapter-6-filtering-xml.txt:236,搜「Document order」)。原文:「"Document order" is a central concept to XML. It is the basis for node order comparisons」;<<左先于右、>>左后于右、is判同一节点。 ↩ -
出处:「Chapter 6: Filtering XML」第 244–260 段(
text/10-ch06-chapter-6-filtering-xml.txt:245,搜「first instance」)。Education 与 Occupation 的文档序比较返回 true,「because the <Education> element appears before the <Occupation> element in document order」。 ↩ -
出处:「Chapter 6: Filtering XML」第 262–284 段(
text/10-ch06-chapter-6-filtering-xml.txt:262,搜「implicit conversion」)。原文:「XML filtering does not support the implicit conversion between data types and returns an error」;「String type values need to be surrounded by double quotes, and numeric type values do not」。 ↩↩ -
出处:「Chapter 6: Filtering XML」第 262–279 段(
text/10-ch06-chapter-6-filtering-xml.txt:265,搜「xs:string type」)。Listing 6-6 把 9000 写成字符串触发类型转换错误;TotalPurchaseYTD 期望 xs:decimal,字符串实现则报错。 ↩↩ -
出处:「Chapter 6: Filtering XML」第 285–311 段(
text/10-ch06-chapter-6-filtering-xml.txt:303,搜「xs:date()」)。三个函数 xs:date()/xs:time()/xs:dateTime();「"Z" is the zero meridian…the Z specifier ("Z" actually means UTC offset of +00:00)」。 ↩ -
出处:「Chapter 6: Filtering XML」第 657–658 段(
text/10-ch06-chapter-6-filtering-xml.txt:657,搜「case-sensitive as well」)。原文:「All operators within XQuery are case-sensitive as well. To avoid errors, utilize "and" and "or" operators in lowercase only」。 ↩↩ -
出处:「Chapter 6: Filtering XML」第 313–348 段(
text/10-ch06-chapter-6-filtering-xml.txt:320,搜「double forward slashes」)。原文:「"//" (shortcut for /descendant-or-self::node()/)」「Resume.nodes('//ns:Tel.Number')」。 ↩ -
出处:「Chapter 6: Filtering XML」第 384–388 段(
text/10-ch06-chapter-6-filtering-xml.txt:387,搜「performance problems」)。原文:「it could cause performance problems during the XML…Chapter 7 will provide more details about the nodes() method's performance optimization」。 ↩↩↩ -
出处:「Chapter 6: Filtering XML」第 438–446 段(
text/10-ch06-chapter-6-filtering-xml.txt:444,搜「access the values」)。原文:「The SQL Server XQuery function sql:variable() allows your XQuery query expression to access the values of T-SQL variables or parameters」。 ↩ -
出处:「Chapter 6: Filtering XML」第 474–483 段(
text/10-ch06-chapter-6-filtering-xml.txt:477,搜「comparisonOperator」)。两种语法:「parentElement[childElement comparisonOperator sql:variable("@varible")]」与「parentElement[@attribute comparisonOperator sql:variable("@varible")]」。 ↩ -
出处:「Chapter 6: Filtering XML」第 504–508 段(
text/10-ch06-chapter-6-filtering-xml.txt:506,搜「Msg 2395」)。原文:「the function is case sensitive and must be referenced in lowercase only. Any other case implementation will trigger the error: Msg 2395」「a variable name that is sent to the sql:variable() function is not case sensitive」。 ↩↩ -
出处:「Chapter 6: Filtering XML」第 484–502 段(
text/10-ch06-chapter-6-filtering-xml.txt:489,搜「0-25000」)。存储过程连跑五档:'0-25000'、'25001-50000'、'50001-75000'、'75001-100000'、'greater than 100000'。 ↩ -
出处:「Chapter 6: Filtering XML」第 538–548 段(
text/10-ch06-chapter-6-filtering-xml.txt:540,搜「not intuitive」)。原文:「The most common mistake that DBAs and developers make is that they try to adopt the IN predicate from T-SQL…However, the solution is much simpler」;语法:「parentElement[childElement = (value1, value2, value3,...)]」。 ↩↩↩ -
出处:「Chapter 6: Filtering XML」第 648–655 段(
text/10-ch06-chapter-6-filtering-xml.txt:652,搜「same functionality as the BEWTEEN」)。原文:「T-SQL has the BETWEEN operator as an additional option…However, the XQuery filter "elementName >= value and elementName <= value" implements the same functionality」。 ↩↩ -
出处:「Chapter 6: Filtering XML」第 576–587 段(
text/10-ch06-chapter-6-filtering-xml.txt:577,搜「two arguments」)。原文:「The XQuery contains() function has two arguments: An XML instance element or attribute; A string pattern」;「similar to the T-SQL LIKE operator when the argument is surrounded by wildcards」。 ↩↩ -
出处:「Chapter 6: Filtering XML」第 588–614 段(
text/10-ch06-chapter-6-filtering-xml.txt:588,搜「does not support」)。原文:「SQL Server does not support the XQuery functions fn:starts-with() and fn:ends-with()」;混合方案:CTE 内 fn:contains 粗筛,外层WHERE Occupation LIKE 'Manual%'精筛。 ↩↩↩ -
出处:「Chapter 6: Filtering XML」第 685–704 段(
text/10-ch06-chapter-6-filtering-xml.txt:701,搜「or DateFirstPurchase」)。完整表达式:「IndividualSurvey[ TotalPurchaseYTD >= 1001 and TotalPurchaseYTD <= 1004 and CommuteDistance = "0-1 Miles" or DateFirstPurchase > xs:date("2004-07-30") ]」。 ↩ -
出处:「Chapter 6: Filtering XML」第 743–755 段(
text/10-ch06-chapter-6-filtering-xml.txt:744,搜「three negative operators」)。原文:「"!=" not equal operator for a general comparison」「"ne" not equal operator for a value comparison」「fn:not() function for a list and range of values」。 ↩↩ -
出处:「Chapter 6: Filtering XML」第 788–796 段(
text/10-ch06-chapter-6-filtering-xml.txt:789,搜「checks if」)。原文:「The fn:empty() function checks if the XML instance elements and attribute values are empty or not」;「IndividualSurvey[ fn:not( fn:empty( Occupation ) )」。 ↩ -
出处:「Chapter 6: Filtering XML」第 783–786 段(
text/10-ch06-chapter-6-filtering-xml.txt:783,搜「alternative to the exist」)。原文:「The exist() method is not supported in the nodes() method. Therefore, fn:empty() and fn:not() work very well within the nodes() method, similarly to the functionality of T-SQL IS NULL and IS NOT NULL operators」。 ↩↩ -
出处:「Chapter 6: Filtering XML」第 819–835 段(
text/10-ch06-chapter-6-filtering-xml.txt:821,搜「advantage over the exist」)。计时:fn:empty() 「CPU time = 454 ms, elapsed time = 496 ms」;exist() 「CPU time = 485 ms, elapsed time = 577 ms」;「The output on your PC could return different performance numbers」。 ↩↩ -
出处:「Chapter 6: Filtering XML」第 842–904 段(
text/10-ch06-chapter-6-filtering-xml.txt:844,搜「inefficient solution」)与第 903–904 段(text/10-ch06-chapter-6-filtering-xml.txt:903,搜「more than twice」)。原文:「This is an inefficient solution…because the T-SQL WHERE clause filters the XML when the engine returns the result set, while the XQuery returns the filtered values」「the result…demonstrates that XQuery is more than twice as efficient as compared to the WHERE clause. Therefore, XQuery filtering should be your first choice」。 ↩↩↩↩↩ -
出处:「Chapter 6: Filtering XML」第 837–841 段(
text/10-ch06-chapter-6-filtering-xml.txt:839,搜「comprehensive filtering mechanism」)。原文:「The T-SQL WHERE clause provides a more comprehensive filtering mechanism compared to XQuery internal filtering. However…XQuery has sufficient ability to filter an XML instance」。 ↩