# 動態SQL常用標籤(where、choose、trim、foreach)
###### tags: `Mybatis-動態SQL`
## where標籤的使用
where在sql使用上,是用來指定條件,如下:
```xml=
<select id="queryBlogIF" parameterType="map" resultType="blog">
<!--where 1 = 1 必定為真-->
select * from mybatis.blog where
<if test="title != null">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</select>
```
當正常使用,沒有出現拼接問題時顯示正常,如下:
```java=
public void queryBlogIF(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap hashMap = new HashMap();
//放入不同參數實現動態查詢
//例如想要用title或是author查詢,都可以直接操作
hashMap.put("title","first");
// hashMap.put("author","houdongun");
List<Blog> blogs = mapper.queryBlogIF(hashMap);
for(Blog blog:blogs){
System.out.println(blog);
}
sqlSession.close();
}
```

但是以下寫法就會出現問題
```java=
@Test
public void queryBlogIF(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap hashMap = new HashMap();
//放入不同參數實現動態查詢
//例如想要用title或是author查詢,都可以直接操作
// hashMap.put("title","first");
hashMap.put("author","houdongun");
List<Blog> blogs = mapper.queryBlogIF(hashMap);
for(Blog blog:blogs){
System.out.println(blog);
}
sqlSession.close();
}
```

### 原因:
因為sql語句缺少中間的 title = #{title},因此變成下面的樣子,並不符合與法規範,因此報錯
```sql=
select * from mybatis.blog where and author = #{author}
```
### 解決方法:改使用<where>標籤
where 元素只會在子元素返回任何內容的情況下才插入 “WHERE” 子句。而且,若子句的開頭為 “AND” 或 “OR”,where 元素也會將它們去除。
```xml=
<select id="queryBlogIF" parameterType="map" resultType="blog">
<!--where 1 = 1 必定為真-->
select * from mybatis.blog
<where>
<if test="title != null">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</where>
</select>
```

## choose、when、otherwise
有時候,我們不想使用所有的條件,而只是想從多個條件中選擇一個使用。針對這種情況,MyBatis 提供了 choose 元素,它有點像 Java 中的 switch 語句。
還是上面的例子,但是策略變為:傳入了 “title” 就按 “title” 查找,傳入了 “author” 就按 “author” 查找的情形。若兩者都沒有傳入,就用views來查找
```xml=
<select id="queryBlogChoose" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<choose>
<when test="title != null">
title = #{title}
</when>
<when test="author != null">
and author = #{author}
</when>
<otherwise>
and where views = #{views}
</otherwise>
</choose>
</where>
</select>
```
不使用任何條件:找出所有資料

hashMap.put("title","first");
使用title查詢

hashMap.put("title","first");
hashMap.put("author","houdongun");
同時使用兩個條件,因為使用<when>標籤,因此前面的"title"符合後,就不會使用後面的"author"條件查詢

## set
set 元素會動態地在行首插入 SET 關鍵字,並會刪掉額外的逗號
```xml=
<update id="updateBlog" parameterType="map">
update mybatis.blog
<set>
<if test="title != null">
title = #{title},
</if>
<if test="author != null">
author = #{author}
</if>
</set>
where id = #{id}
</update>
```
#### 測試1:改兩項
```java=
hashMap.put("title","firstTest");
hashMap.put("author","houdongun");
hashMap.put("id","800f804df7874eeaa410699e5bfd3d7d");
```
sql句型

結果

#### 測試2:只改一項
```
hashMap.put("author","覺大人");
hashMap.put("id","800f804df7874eeaa410699e5bfd3d7d");
```
sql語句,自動將多的","並加入"set"

結果

### 總結:
**所謂的動態SQL,本質上還是SQL語句,只是我們可以在SQL層面,去執行一個邏輯代碼**