什么是动态SQL?

就是相对与固定SQL。就是通过传入的参数不一样,可以组成不同结构的SQL语句. 这种根据参数的条件修改SQL结构的SQL语句,我们称为动态SQL语句.

If 使用

<select id="selectByCondition" resultType="com.mybatis.pojo.User">
		<!-- 错误写法	select * from user where name like '%#{name}%' or age = #{age} -->
	  	<!-- 
	  		正确写法:
	  		select * from user where name like concat('%',#{name},'%') or age = #{age}
	  		或者传值加上%
	  		上述SQL语句的语义来说,是一个静态SQL语句,一开始已经确定SQL的语义的
	  		不管有没有数据,都会对全部数据进行修改,如果某一个数据没有,name会自动设置为null
	  		不符合实际场景
	  		解决方案: 使用MyBatis的动态SQL语句
	  	 -->
	  	 select * from user where
	  	 <if test="name!=null and name!=''">
	  	 	name like concat('%',#{name},'%')
	  	 </if>
	  	 <if test="age!=null and age!=''">
	  	 	or age = #{age}
	  	 </if>
	</select>

我们会发现当都不传时,sql语句为:select * from user where。会报错。
当我门只传age值时,sql语句为:select * from user where or age=1。会报错。
因此需要另一个标签解决,这个标签就是where

where标签

1.当编写 where 标签时,如果内容中第一个是 and/or 去掉第一个 and/or


2. 如果中有内容会生成 where 关键字,如果没有内容不 生成 where 关键

<select id="selectByCondition" resultType="com.mybatis.pojo.User">
		<!-- 错误写法	select * from user where name like '%#{name}%' or age = #{age} -->
	  	<!-- 
	  		正确写法1:
	  		select * from user where name like concat('%',#{name},'%') or age = #{age}
	  		或者传值加上%
	  		上述SQL语句的语义来说,是一个静态SQL语句,一开始已经确定SQL的语义的
	  		不管有没有数据,都会对全部数据进行修改,如果某一个数据没有,name会自动设置为null
	  		不符合实际场景
	  		解决方案: 使用MyBatis的动态SQL语句
	  	 -->
	  	 select * from user
	  	 <where>
		  	 <if test="name!=null and name!=''">
		  	 	name like concat('%',#{name},'%')
		  	 </if>
		  	 <if test="age!=null and age!=''">
		  	 	or age = #{age}
		  	 </if>
	  	 </where>
	</select>

sql与include标签

1.某些 SQL 片段如果希望复用,可以使用定义这个片段
2.sql片段用include标签引入

<select id="selectByCondition" resultType="com.mybatis.pojo.User">
		<!-- 错误写法	select * from user where name like '%#{name}%' or age = #{age} -->
	  	<!-- 
	  		正确写法1:
	  		select * from user where name like concat('%',#{name},'%') or age = #{age}
	  		或者传值加上%
	  		上述SQL语句的语义来说,是一个静态SQL语句,一开始已经确定SQL的语义的
	  		不管有没有数据,都会对全部数据进行修改,如果某一个数据没有,name会自动设置为null
	  		不符合实际场景
	  		解决方案: 使用MyBatis的动态SQL语句
	  	 -->
	  	 select * from user
	  	 <!-- include:引入sql片段 -->
	  	 <include refid="selectSql"/>
	</select>
	<!-- sql片段:
			id:唯一标识 
	-->
	<sql id="selectSql">
		<where>
		  	<if test="name!=null and name!=''">
		  	 	name like concat('%',#{name},'%')
		  	 </if>
		  	 <if test="age!=null and age!=''">
		  	 	or age = #{age}
		  	 </if>
	  	 </where>
	</sql>
	
	<select id="selectTotalByCondition" resultType="long">
		select count(*) from user
		<include refid="selectSql"/>
	</select>

set标签的使用

1.作用:去掉最后一个逗号

2.作用:如果里面有内容生成 set 关键字,没有就不生成

3.id=#{id} 目的防止中没有内容,mybatis 不生成 set 关键字,如果修改中没有 set 从句 SQL 语法错误.

<update id="updateUserByNotNull">
		update user
		<set>
			id=#{id}
			<if test="username!=null and username!=''">
				username=#{username},
			</if>
			<if test="password!=null and password!=''">
				password=#{password},
			</if>
			<if test="age!=null and age!=''">
				age=#{age},
			</if>
		</set>
		where id=#{id}
	</update>

trim标签

1.prefix:在trim标签里的成立sql语句前面添加prefix值,一般prefix值为where/set

2.prefixOverrides:去掉在trim标签里的成立sql语句前面第一个关键字,一般是and /or

3.suffix:在trim标签里的成立sql语句后面添加suffix值

4.suffixOverrieds:去掉在trim标签里的成立sql语句最后面一个字符,一般是,逗号

–prefix

<select id="selectByCondition" resultType="com.mybatis.pojo.User">
	  	 select * from user
	  	 <include refid="selectSql"/>
	</select>
	<sql id="selectSql">
	  	 <trim prefix="where">
	  	 	<if test="username!=null and username!=''">
		  	 	username like concat('%',#{username},'%')
		  	 </if>
	  	 </trim>
	</sql>

当username有值时,sql语句为:select * from user where username like concat(’%哥%’)

–prefixOverrides

<select id="selectByCondition" resultType="com.mybatis.pojo.User">
	  	 select * from user
	  	 <!-- include:引入sql片段 -->
	  	 <include refid="selectSql"/>
	</select>
	<!-- sql片段:      id:唯一标识 -->
	<sql id="selectSql">
		<!-- 注意:and|or不能写成and | or,不能有空格 -->
	  	 <trim prefix="where" prefixOverrides="and|or">
	  	 	<if test="username!=null and username!=''">
		  	 	and username like concat('%',#{username},'%')
		  	 </if>
		  	 <if test="age!=null and age!=''">
		  	 	or age = #{age}
		  	 </if>
	  	 </trim>
	</sql>

当只有username有值时,sql语句为:select * from user where username like concat(’%’,#{username},’%’)
当只有age有值时,sql语句为:select * from user where age = #{age}
当两个都有值时,sql语句为:select * from user where username like concat(’%’,?,’%’) or age = ?

–suffixOverrieds

<update id="updateUserByNotNull">
		update user
		<trim prefix="set" suffixOverrides=",">
			id=#{id},
			<if test="username!=null and username!=''">
				username=#{username},
			</if>
			<if test="password!=null and password!=''">
				password=#{password},
			</if>
			<if test="age!=null and age!=''">
				age=#{age},
			</if>
		</trim>
		where id=#{id}
	</update>

–suffix

<update id="updateUserByNotNull">
		update user
		<trim prefix="set" suffixOverrides="," suffix="where id=#{id}">
			id=#{id},
			<if test="username!=null and username!=''">
				username=#{username},
			</if>
			<if test="password!=null and password!=''">
				password=#{password},
			</if>
			<if test="age!=null and age!=''">
				age=#{age},
			</if>
		</trim>
	</update>

foreach标签

1.collectino=”” 要遍历的集合

2.item 迭代变量, #{迭代变量名}获取内容

3. open 循环后左侧添加的内容

4. close 循环后右侧添加的内容

5. separator 每次循环时,元素之间的分隔符

实例1:

<delete id="deleteByIds">
		delete from user where id in
		<foreach collection="ids" item="id" close=")" open="(" separator=",">
			#{id}
		</foreach>
	</delete>

实例2:

<insert id="insertByBatch">
		insert into user(username,password,age) values
		<foreach collection="users" item="user" separator=",">
			(#{user.username},#{user.password},#{user.age})
		</foreach>
	</insert>