SQL语句解析
SQL语句解析
- 左外连接
<select id="pageQuery" resultType="com.sky.vo.DishVO">select d.*,c.name as categoryName from dish d left outer join category c on d.category_id = c.id</select>
left outer join category c
left outer join
是 SQL 中的连接类型之一。它的作用是返回左边表(在这里是dish
表)的所有记录,即使右边的表(category
)没有匹配的记录,也会返回左边表的记录。- 左连接(LEFT JOIN):左连接会返回左表中的所有行,即使右表没有匹配的行。如果右表中没有匹配的行,那么右表的列会返回
NULL
。 - 外连接(OUTER JOIN):指的是返回所有行,而不仅仅是有匹配行的记录。通常,如果没有匹配的行,右表的列值会是
NULL
。
- 左连接(LEFT JOIN):左连接会返回左表中的所有行,即使右表没有匹配的行。如果右表中没有匹配的行,那么右表的列会返回
在这里:
category c
表示右边的表是category
,并为它指定了别名c
。- 从
dish
表中选取所有字段(d.*
),并从category
表中选取name
字段,重命名为categoryName
。 - 使用
LEFT OUTER JOIN
将dish
表与category
表通过category_id
和id
进行连接。- 这意味着:即使某个菜品没有对应的分类(即
dish.category_id
在category
表中找不到匹配的id
),这个菜品的信息仍然会被返回,只是分类名称会显示为NULL
。
- 这意味着:即使某个菜品没有对应的分类(即
模糊查寻
<where><if test="name != null and name != ''">and d.name like concat('%',#{name},'%')</if><if test="categoryId != null">and d.category_id = #{categoryId}</if><if test="status != null">and d.status = #{status}</if></where>
1. <where>
标签的作用
<where>
标签用于自动为 SQL 语句添加 WHERE
子句,并根据 <if>
条件判断来动态构建查询条件。
- 自动添加 WHERE 关键字:当你在
<where>
标签中添加多个<if>
条件时,MyBatis 会自动添加WHERE
关键字,并在每个条件之间添加AND
。如果第一个条件存在,则 MyBatis 会在 SQL 中添加WHERE
,之后的条件会自动加上AND
。如果没有任何条件满足,则WHERE
关键字会被省略。
2. <if>
标签
每个 <if>
标签包含一个条件,当条件为 true
时,才会将对应的 SQL 片段添加到查询语句中。test
属性是条件判断的关键所在。
解析你的代码:
<where><if test="name != null and name != ''">and d.name like concat('%',#{name},'%')</if><if test="categoryId != null">and d.category_id = #{categoryId}</if><if test="status != null">and d.status = #{status}</if>
</where>
2.1 模糊查询(like
)
and d.name like concat('%',#{name},'%')
这一行表示对dish
表中的name
字段进行模糊查询。这里使用了like
操作符,它用来进行字符串匹配查找。like
查询会根据给定的值在字段中查找符合条件的记录。%
是 SQL 中的通配符,表示匹配任意数量的字符。concat('%',#{name},'%')
:concat
是一个字符串拼接函数,它会将%
与传入的name
参数连接起来。例如,如果#{name}
的值是"Pizza"
,则concat('%', 'Pizza', '%')
会变成"%Pizza%"
,这是一个模糊查询,表示查找包含"Pizza"
的所有记录。- 模糊查询的例子:
-
假设
name
的值为"Pizza"
,那么 SQL 语句会变成:and d.name like '%Pizza%'
这表示查找
dish
表中所有名字中包含"Pizza"
的记录。
-
2.2 categoryId != null
and d.category_id = #{categoryId}
:这行表示当传入的categoryId
不为null
时,才会添加该条件。它会精确匹配dish
表中的category_id
字段。-
例如,如果
categoryId
的值为2
,那么 SQL 语句会变成:and d.category_id = 2
-
如果
categoryId
为null
,则这条条件不会被添加到 SQL 语句中。
-
2.3 status != null
and d.status = #{status}
:这一行表示当status
不为null
时,才会加上该条件。它会精确匹配dish
表中的status
字段。-
例如,如果
status
的值为1
,那么 SQL 语句会变成:and d.status = 1
-
如果
status
为null
,则这条条件不会被添加到 SQL 语句中。
-
3. 总结模糊查询和 concat
的作用
- 模糊查询(
like
):like
操作符用于在 SQL 中进行模糊匹配,可以用于查找包含指定字符的记录。使用通配符%
,可以在字符串的任意位置进行模糊匹配。 concat
函数:concat
是一个字符串连接函数,通常用于将多个字符串拼接成一个字符串。在模糊查询中,concat('%', #{name}, '%')
用来动态构建包含通配符的查询条件,以便在 SQL 查询中实现模糊匹配。
动态sql
<select id="getSetmealIdByDishIds" resultType="java.lang.Long">select setmeal_id from setmeal_dish where dish_id in<foreach collection="dishIds" item="dishId" open="(" separator="," close=")">#{dishId}</foreach></select>
这段代码是一个 MyBatis 的 动态 SQL 查询语句,它用于根据传入的 dishIds
查找 setmeal_id
。动态 SQL 是 MyBatis 提供的一种灵活的方式,用于根据不同的查询条件动态构建 SQL 语句。下面我将逐行讲解这段代码的实现。
1. 方法签名与 select
标签:
<select id="getSetmealIdByDishIds" resultType="java.lang.Long">select setmeal_id from setmeal_dish where dish_id in
id="getSetmealIdByDishIds"
:这是该 SQL 映射语句的唯一标识符,你可以在 Java 代码中通过sqlSession.selectList("getSetmealIdByDishIds", params)
调用它。resultType="java.lang.Long"
:指定查询结果的类型,这里返回的是Long
类型,表示查询结果将是setmeal_id
的值。- SQL 查询语句的主体部分:
select setmeal_id from setmeal_dish where dish_id in
。
2. <foreach>
标签:
<foreach collection="dishIds" item="dishId" open="(" separator="," close=")">#{dishId}
</foreach>
<foreach>
是 MyBatis 提供的一个标签,用于动态生成一个 IN
子句中的多个值。它会根据传入的 dishIds
集合,动态生成 SQL 语句的内容。
解释各个属性:
collection="dishIds"
:指定了foreach
遍历的集合对象。dishIds
是传入的参数,可能是一个List<Long>
或其他类型的集合。item="dishId"
:指定集合中的每一个元素的名称。在这个例子中,每次遍历时,dishId
代表集合中的一个元素。open="("
:表示生成 SQL 中IN
子句的开始部分,即(
。separator=","
:表示在生成每个dishId
值之间使用逗号,
作为分隔符。close=")"
:表示生成 SQL 中IN
子句的结束部分,即)
。
生成的 SQL:
假设传入的 dishIds
是 [1, 2, 3]
,那么 <foreach>
会生成以下 SQL 部分:
sql
复制编辑
(1, 2, 3)
3. 完整 SQL 查询:
最终生成的 SQL 查询语句是:
sql
复制编辑
select setmeal_id from setmeal_dish where dish_id in (1, 2, 3)
- 这里,
setmeal_id
是要查询的字段,setmeal_dish
是表名,dish_id in (1, 2, 3)
表示查询所有dish_id
在[1, 2, 3]
中的记录。
4. 动态 SQL 的作用:
<foreach>
标签 的作用是将dishIds
集合中的元素动态地拼接到 SQL 查询中的IN
子句。这样,无论你传入多少个dishIds
,MyBatis 都会自动生成相应的 SQL 查询。- 如果传入的
dishIds
集合为空,MyBatis 会生成一个空的IN
子句(IN ()
),这时查询可能会失败,因此通常需要在传入参数前进行有效性检查,确保集合不为空。
5. 总结:
这段代码实现了一个动态 SQL 查询,用于根据一组 dishIds
查找与之关联的 setmeal_id
。其中,<foreach>
标签动态生成了 SQL 中 IN
子句的内容,使得可以根据不同的 dishIds
生成相应的 SQL 查询。动态 SQL 在处理这种变长查询条件时非常有用,可以避免手动拼接 SQL 字符串的麻烦,并且提高代码的可维护性。