编写XQuery函数调用序列:如何避免冗余let $tmp赋值语句
解决XQuery中冗余
let $tmp :=赋值的替代方案 你当前的代码里用大量let $tmp :=来包裹trace、sql:execute这类副作用操作,本质是为了满足FLOWR表达式的语法要求——FLOWR只能包含for/let/where/order by/return子句,不能直接裸写执行语句。以下是几种无需冗余赋值的实现方式:
1. 标准XQuery方案:用序列表达式组织操作
直接把所有需要执行的操作放在return的序列中,XQuery会按顺序执行序列里的每个子表达式,忽略它们的返回值(或合并成空序列),完全符合语法要求:
declare function module:import($xmlsrc as xs:string, $conn as xs:anyURI) { let $root := module:getXml($xmlsrc) return ( (: 处理Table01 :) trace("Table01"), sql:execute($conn, "insert into Table01 (rel1,rel2,rel3,rel4,rel5) values(" || 2 || ", '" || $root//myns:ftr[@n='abc']/myns:ftr[@type='p1'] || "', '" || $root//myns:ftr[@n='abc']/myns:ftr[@type='p2'] || "', '" || $root//myns:ftr[@n='abc']/myns:ftr[@type='p3'] || "', '" || $root//myns:ftr[@n='abc']/myns:ftr[@type='p4'] || "')"), (: 处理Table02 :) sql:execute($conn, "insert into Table02 (rel1,rel2,rel3,rel4,rel5) values(" || 3 || ", '" || $root//myns:div[@n='abc']/myns:xyz[@type='p5'] || "', '" || $root//myns:div[@n='abc']/myns:xyz[@type='p6'] || "', '" || $root//myns:div[@n='abc']/myns:xyz[@type='p7'] || "', '" || $root//myns:div[@n='abc']/myns:xyz[@type='p8'] || "')"), (: 更多表操作 :) () ) };
2. 扩展语法方案:使用do语句(需处理器支持)
部分XQuery处理器(如支持XQuery Update Facility或扩展语法的)提供do { ... }语法,专门用于执行副作用操作,无需绑定变量:
declare function module:import($xmlsrc as xs:string, $conn as xs:anyURI) { let $root := module:getXml($xmlsrc) return ( do { trace("Table01") }, do { sql:execute($conn, "insert into Table01 (rel1,rel2,rel3,rel4,rel5) values(" || 2 || ", '" || $root//myns:ftr[@n='abc']/myns:ftr[@type='p1'] || "', '" || $root//myns:ftr[@n='abc']/myns:ftr[@type='p2'] || "', '" || $root//myns:ftr[@n='abc']/myns:ftr[@type='p3'] || "', '" || $root//myns:ftr[@n='abc']/myns:ftr[@type='p4'] || "')") }, do { sql:execute($conn, "insert into Table02 ...") } ) };
注意:do不是标准XQuery 1.0语法,使用前需确认你的处理器支持该扩展。
3. 优化方案:封装重复逻辑为子函数
如果有大量类似的SQL插入操作,建议把SQL拼接和执行逻辑封装成子函数,既消除冗余赋值,又提升代码可维护性:
declare function module:insert-table($conn as xs:anyURI, $table-name as xs:string, $id as xs:integer, $column-values as xs:string*) { let $sql := concat( "insert into ", $table-name, " (rel1,rel2,rel3,rel4,rel5) values(", $id, ", '", string-join($column-values, "', '"), "')" ) return sql:execute($conn, $sql) }; declare function module:import($xmlsrc as xs:string, $conn as xs:anyURI) { let $root := module:getXml($xmlsrc) return ( trace("Table01"), module:insert-table( $conn, "Table01", 2, ($root//myns:ftr[@n='abc']/myns:ftr[@type='p1'], $root//myns:ftr[@n='abc']/myns:ftr[@type='p2'], $root//myns:ftr[@n='abc']/myns:ftr[@type='p3'], $root//myns:ftr[@n='abc']/myns:ftr[@type='p4']) ), module:insert-table( $conn, "Table02", 3, ($root//myns:div[@n='abc']/myns:xyz[@type='p5'], $root//myns:div[@n='abc']/myns:xyz[@type='p6'], $root//myns:div[@n='abc']/myns:xyz[@type='p7'], $root//myns:div[@n='abc']/myns:xyz[@type='p8']) ) ) };
内容的提问来源于stack exchange,提问作者user18451290
相关产品推荐
相关产品推荐

