T_SQL 遍历 XML

博客展示了XML数据的操作示例,通过SQL代码定义XML数据,包含书籍信息。接着进行节点遍历,输出每个书籍子元素内容;还进行属性遍历,输出属性位置、名称和值,为XML数据处理提供了参考。

declare @data XML;
set @data='<bookstore>
 <book category="COOKING" isbn="3434343" > 
  <title lang="en">Everyday Italian</title>
  <author>Giada De Laurentiis</author>
  <year>2005</year> 
  <price>30.00</price>
 </book>
 <book category="CHILDREN"> 
  <title lang="jp">Harry Potter</title> 
  <author>J K. Rowling</author> 
  <year>2005</year> 
  <price>29.99</price>
 </book>
 <book category="WEB"> 
  <title lang="en">XQuery Kick Start</title>
  <author>James McGovern</author> 
  <author>Per Bothner</author> 
  <author>Kurt Cagle</author> 
  <author>James Linn</author> 
  <author>Vaidyanathan Nagarajan</author> 
  <year>2003</year> 
  <price>49.99</price>
 </book>
 <book category="WEB">
  <title lang="cn">Learning XML</title>
  <author>Erik T. Ray</author>
  <year>2003</year>
  <price>39.95</price>
 </book>
</bookstore>';

--遍历节点
DECLARE @count INT, @totalCount INT, @child XML, @attributeName VARCHAR(30), @attributeValue VARCHAR(30);
SET @count=1;
SET @totalCount=@data.value('count(/bookstore/book)','INT');
PRINT ''
While @count<=@totalCount
BEGIN
 SET @child=@data.query('/bookstore/book[position()=sql:variable("@count")]')
 PRINT 'Processing Child Element:' + CAST(@count AS VARCHAR)
 PRINT 'Child element: ' + CAST(@child AS VARCHAR(max))
 PRINT ''
 SET @count=@count+1
END


--遍历属性
SET @count=1;
SET @totalCount=@data.value('count(/bookstore/book[1]/@*)','INT');
WHILE @count<=@totalCount
BEGIN
 SET @attributeName = @data.value(
  'local-name((/bookstore/book/@*[position()=sql:variable("@count")])[1])'
  , 'VARCHAR(30)')      
    SET @attributeValue = @data.value(
  '(/bookstore/book/@*[position()=sql:variable("@count")])[1]'
  ,'VARCHAR(30)') 
    PRINT 'Attribute Position: ' + CAST(@count AS VARCHAR)
    PRINT 'Attribute Name: ' + @attributeName   
    PRINT 'Attribute Value: ' + @attributeValue  
    PRINT ''   
    SET @count = @count + 1
END

转载于:https://www.cnblogs.com/Tim-Yi/archive/2011/10/25/2223926.html

<think>我们正在使用MyBatis框架,目标是在XML映射文件中编写SQL语句时,遍历一个集合(如List)来动态生成SQL片段。例如,我们有一个ID列表,想生成类似`DELETE FROM emp WHERE id IN (1,2,3)`的SQL语句。 根据引用[1]和引用[2],MyBatis提供了`<foreach>`标签来实现这一功能。下面详细说明如何使用: ### `<foreach>`标签关键属性 - **collection**:指定要遍历的集合或数组。注意:如果传入的是List,可以使用"list"作为别名;如果是数组,使用"array";如果使用@Param注解指定了参数名,则使用该名称。 - **item**:指定遍历过程中每个元素的引用名称(变量名),在SQL片段中通过`#{变量名}`引用。 - **index**(可选):遍历列表或数组时,表示当前元素的索引;遍历Map时,表示键。 - **open**(可选):遍历开始前拼接的字符串。 - **separator**(可选):每次遍历之间拼接的分隔符。 - **close**(可选):遍历结束后拼接的字符串。 ### 示例:根据ID列表删除记录 假设我们有一个Mapper接口方法: ```java int deleteByIds(@Param("ids") List<Integer> ids); ``` 在XML映射文件中,可以这样写: ```xml <delete id="deleteByIds"> DELETE FROM emp WHERE id IN <foreach collection="ids" item="id" separator="," open="(" close=")"> #{id} </foreach> </delete> ``` ### 解释 - `collection="ids"`:对应方法参数中@Param("ids")指定的名称。 - `item="id"`:将每个元素命名为`id`,在`#{id}`中使用。 - `open="("`:在遍历开始前添加左括号。 - `separator=","`:每次遍历后添加逗号(最后一次不加)。 - `close=")"`:遍历结束后添加右括号。 生成的SQL语句为: ```sql DELETE FROM emp WHERE id IN ( ? , ? , ? ) ``` 实际执行时,`?`会被替换为具体的id值。 ### 其他常见用法 #### 1. 遍历集合插入多条记录 ```xml <insert id="batchInsert"> INSERT INTO emp (name, dept) VALUES <foreach collection="empList" item="emp" separator=","> (#{emp.name}, #{emp.dept}) </foreach> </insert> ``` #### 2. 遍历数组更新记录 ```xml <update id="updateStatus"> UPDATE emp SET status = 1 WHERE id IN <foreach collection="array" item="id" open="(" separator="," close=")"> #{id} </foreach> </update> ``` 注意:当方法参数为数组且未使用@Param注解时,collection使用"array"。 ### 注意事项 1. **集合类型**:确保传入的参数是集合类型(List, Set, Map, 数组等)。 2. **参数名**:如果方法只有一个集合参数且未使用@Param注解,则: - 如果参数类型是List,默认使用"list"。 - 如果参数类型是数组,默认使用"array"。 3. **SQL注入安全**:`<foreach>`生成的占位符`#{}`是预编译的,能防止SQL注入。 ### 引用说明 - 引用[1]和[2]介绍了`<foreach>`标签的基本用法和属性[^1][^2]。 - 引用[3]和[4]提供了MyBatis配置和映射文件处理的背景[^3][^4]。 §§相关问题§§ 1. 如何在MyBatis中传递多个集合参数? 2. 使用`<foreach>`时如何避免SQL语句过长(如IN列表超长)? 3. MyBatis中除了`<foreach>`还有哪些动态SQL标签? 4. 如何调试MyBatis动态SQL生成的最终语句?</think>在 MyBatis 的 XML 映射文件中,使用 `<foreach>` 标签可以高效地遍历集合并生成动态 SQL 语句。以下是详细实现步骤和示例: ### 核心步骤 1. **定义 Mapper 接口方法** 在 Java 接口中声明方法,参数为集合类型(如 `List`, `Set`, 数组等): ```java // EmpMapper.java int deleteByIds(@Param("ids") List<Integer> ids); // 使用@Param指定参数名 ``` 2. **XML 中使用 `<foreach>` 标签** 在 XML 映射文件中配置 SQL,通过 `<foreach>` 遍历集合: ```xml <delete id="deleteByIds"> DELETE FROM emp WHERE id IN <foreach collection="ids" <!-- 参数名,需与@Param一致 --> item="id" <!-- 遍历元素的变量名 --> open="(" <!-- 遍历开始前添加的字符 --> separator="," <!-- 元素间的分隔符 --> close=")"> <!-- 遍历结束后添加的字符 --> #{id} <!-- 引用当前元素 --> </foreach> </delete> ``` ### 关键属性详解 | 属性 | 说明 | 示例值 | |-------------|----------------------------------------------------------------------|--------------| | `collection` | 要遍历的集合参数名(需与 `@Param` 或默认名匹配) | `"ids"` | | `item` | 遍历过程中每个元素的引用变量名 | `"id"` | | `open` | 遍历开始前添加的字符串 | `"("` | | `separator` | 元素之间的分隔符 | `","` | | `close` | 遍历结束后添加的字符串 | `")"` | ### 其他常见用法示例 #### 1. 批量插入数据 ```xml <insert id="batchInsert"> INSERT INTO emp (name, dept) VALUES <foreach collection="empList" item="emp" separator=","> (#{emp.name}, #{emp.dept}) <!-- 引用对象属性 --> </foreach> </insert> ``` #### 2. 动态更新条件 ```xml <update id="updateStatus"> UPDATE emp SET status = 1 WHERE <foreach collection="depts" item="dept" separator="OR"> department = #{dept} <!-- 生成 OR 条件 --> </foreach> </update> ``` #### 3. 遍历数组(无 `@Param` 时) ```xml <select id="selectByIds"> SELECT * FROM emp WHERE id IN <foreach collection="array" item="id" open="(" separator="," close=")"> #{id} </foreach> </select> ``` ### 注意事项 1. **参数名匹配**: - 使用 `@Param("ids")` 时,`collection` 必须为 `"ids"` - 未使用 `@Param` 时: - 单 `List` 参数 → `collection="list"` - 单数组参数 → `collection="array"` 2. **SQL 注入防护**: `#{id}` 使用预编译占位符,MyBatis 会自动处理类型转换和安全过滤[^2]。 3. **性能优化**: 当集合过大时(如 >1000 个元素),考虑分批执行,避免 SQL 过长[^3]。 ### 执行过程说明 1. MyBatis 解析 XML 时,识别 `<foreach>` 标签并提取动态 SQL 逻辑[^3] 2. 运行时根据传入的集合生成实际 SQL,例如: ```sql -- 传入 ids=[101,102,103] 时生成的SQL DELETE FROM emp WHERE id IN (101, 102, 103) ``` 3. 通过 JDBC 预编译执行,确保安全性和性能[^2][^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值