---
# System prepended metadata

title: 動態SQL常用標籤(where、choose、trim、foreach)
tags: [Mybatis-動態SQL]

---

# 動態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();
    }
```
![](https://i.imgur.com/yUsVxlN.png)
但是以下寫法就會出現問題
```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();
    }
```
![](https://i.imgur.com/5LDsgDs.png)
### 原因：
因為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>
```
![](https://i.imgur.com/bajGQzU.png)

## 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>
```
不使用任何條件：找出所有資料
![](https://i.imgur.com/JfgivBN.png)
hashMap.put("title","first");
    
使用title查詢
![](https://i.imgur.com/4iHOERA.png)
    
hashMap.put("title","first");
hashMap.put("author","houdongun");
同時使用兩個條件，因為使用<when>標籤，因此前面的"title"符合後，就不會使用後面的"author"條件查詢
![](https://i.imgur.com/voM9R1n.png)

## 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句型
![](https://i.imgur.com/RFKpjNP.png)
結果
![](https://i.imgur.com/ZgerTmS.png)
    
#### 測試2:只改一項
```
hashMap.put("author","覺大人");
        hashMap.put("id","800f804df7874eeaa410699e5bfd3d7d");
```
sql語句，自動將多的","並加入"set"
![](https://i.imgur.com/DGzkLc6.png)
結果
![](https://i.imgur.com/cYygM9r.png)

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