# 動態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層面,去執行一個邏輯代碼**