9、动态SQL

9、动态SQL

Mybatis框架的动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,它存在的意义是为了解决 拼接SQL语句字符串时的痛点问题。

9.1、if

    //根据条件查询员工信息
    List<Emp>  getEmpByCondition(Emp emp);
    <!--
        动态SQL:
        1. if 通过test属性中的表达式判断标签中的内容是否会拼接到SQL中
    -->
    <!--List<Emp>  getEmpByCondition(Emp emp);-->
    <select id="getEmpByCondition" resultType="emp">
        select * from t_emp where
        <if test="empName != null and empName != ''">
            emp_name = #{empName}
        </if>
        <if test="age != null and age != ''">
            and age = #{age}
        </if>
        <if test="gender != null and gender != ''">
            and gender = #{gender}
        </if>
    </select>

测试:

    @Test
    public void testGetEmpByCondition(){
        SqlSession sqlSession = sqlSessionUtil.getSqlSession();
        SQLMapper mapper = sqlSession.getMapper(SQLMapper.class);
        Emp emp = new Emp(null, "张三", 18, null);
//        for (Emp emp1 : mapper.getEmpByCondition(emp)) {
//            System.out.println(emp1);
//        }

        List<Emp> empByCondition = mapper.getEmpByCondition(emp);
        empByCondition.forEach(System.out::println);
    }

9.2、where


上述存在bug:

        Emp emp = new Emp(null, "", 18, null);
       结果为: select * from t_emp where and age = ?

        Emp emp = new Emp(null, "", null, null);
        结果为:select * from t_emp where

解决办法一

select * from t_emp where 1=1
加上恒成立条件

<select id="getEmpByCondition" resultType="emp">
        select * from t_emp where 1=1
        <if test="empName != null and empName != ''">
            emp_name = #{empName}
        </if>
        <if test="age != null and age != ''">
            and age = #{age}
        </if>
        <if test="gender != null and gender != ''">
            and gender = #{gender}
        </if>
    </select>

解决办法二:

    <!--List<Emp>  getEmpByCondition(Emp emp);-->
    <select id="getEmpByCondition" resultType="emp">
        select * from t_emp 
        <where>
            <if test="empName != null and empName != ''">
                emp_name = #{empName}
            </if>
            <if test="age != null and age != ''">
                and age = #{age}
            </if>
            <if test="gender != null and gender != ''">
                and gender = #{gender}
            </if>
        </where>
    </select>

where和if一般结合使用
若where标签中的if条件都不满足,则where标签没有任何功能,即不会添加where关键字
若where标签中的if条件满足,则where标签会自动添加where关键字,并将条件最前方多余的and去掉
注意:where标签不能去掉条件最后多余的and

9.3、trim

存在的bug:

<select id="getEmpByCondition" resultType="emp">
        select * from t_emp
        <where>
            <if test="empName != null and empName != ''">
                emp_name = #{empName} and
            </if>
            <if test="age != null and age != ''">
                 age = #{age} and
            </if>
            <if test="gender != null and gender != ''">
                 gender = #{gender}
            </if>
        </where>
    </select>
Emp emp = new Emp(null, "张三", 18, null);
结果为:select * from t_emp WHERE emp_name = ? and age = ? and

解决办法

    <select id="getEmpByCondition" resultType="emp">
        select * from t_emp
        <trim prefix="where" suffixOverrides="and">
            <if test="empName != null and empName != ''">
                emp_name = #{empName} and
            </if>
            <if test="age != null and age != ''">
                 age = #{age} and
            </if>
            <if test="gender != null and gender != ''">
                 gender = #{gender}
            </if>
        </trim>
    </select>

trim用于去掉或添加标签中的内容
常用属性:
prefix:在trim标签中的内容的前面添加某些内容
prefixOverrides:在trim标签中的内容的前面去掉某些内容
suffix:在trim标签中的内容的后面添加某些内容
suffixOverrides:在trim标签中的内容的后面去掉某些内容


9.4、choose、when、otherwise

choose、when、 otherwise相当于if…else if…else

    //根据choose来查询员工信息
    List<Emp>  getEmpByChoose(Emp emp);
 <!--List<Emp>  getEmpByChoose(Emp emp);-->
    <select id="getEmpByChoose" resultType="emp">
       select * from t_emp
<where>
    <choose>
        <when test="empName != null and empName != ''">
            emp_name = #{empName}
        </when>
        <when test="age != null and age != ''">
            age = #{age}
        </when>
        <when test="gender != null and gender != ''">
            gender = #{gender}
        </when>
    </choose>
</where>
    </select>

测试

    @Test
    public void testGetEmpByChoose(){
        SqlSession sqlSession = sqlSessionUtil.getSqlSession();
        SQLMapper mapper = sqlSession.getMapper(SQLMapper.class);
        Emp emp = new Emp(null, "张三", 18, null);
        List<Emp> empByCondition = mapper.getEmpByChoose(emp);
        empByCondition.forEach(System.out::println);
    }

数据结果:

select * from t_emp WHERE emp_name = ?

9.5、foreach

批量添加
    //批量添加员工信息
    void insertMoreEmp(@Param("emps") List<Emp> emps);
    <!--void insertMoreEmp(@Param("emps") List<Emp> emps);-->
    <insert id="insertMoreEmp">
        insert into t_emp values
        <foreach collection="emps" item="emp" separator=",">
            (null,#{emp.empName},#{emp.age},#{emp.gender},null)
        </foreach>
    </insert>

测试:

    @Test
    public void testInsertMoreEmp(){
        SqlSession sqlSession = sqlSessionUtil.getSqlSession();
        SQLMapper mapper = sqlSession.getMapper(SQLMapper.class);
        Emp emp0 = new Emp(null, "小明0", 18, "男");
        Emp emp1 = new Emp(null, "小明1", 18, "男");
        Emp emp2 = new Emp(null, "小明2", 18, "男");
        List<Emp> emps = Arrays.asList(emp0, emp1, emp2);
        mapper.insertMoreEmp(emps);

    }
批量删除
    //批量删除员工
    void deleteMoreEmp(@Param("empIds") Integer[] empIds);
    <!--void deleteMoreEmp(@Param("empIds") Integer[] empIds);-->
    <delete id="deleteMoreEmp">
        delete from t_emp where emp_id in
        (
            <foreach collection="empIds" item="empId" separator=",">
                #{empId}
            </foreach>
            )
    </delete>

测试

    @Test
    public void testDeleteMoreEmp(){
        SqlSession sqlSession = sqlSessionUtil.getSqlSession();
        SQLMapper mapper = sqlSession.getMapper(SQLMapper.class);
        Integer[] integers = {11, 12, 13};
        mapper.deleteMoreEmp(integers);
    }

改进:

    <delete id="deleteMoreEmp">
        delete from t_emp where emp_id in
            <foreach collection="empIds" item="empId" separator="," open="(" close=")">
                #{empId}
            </foreach>
    </delete>

改进2:

    <delete id="deleteMoreEmp">
        delete from t_emp where emp_id in
            <foreach collection="empIds" item="empId" separator="or" >
                emp_id = #{empId}
            </foreach>
    </delete>


9.6、SQL片段

sql片段,可以记录一段公共sql片段,在使用的地方通过include标签进行引入

<sql id="empColumns">
        emp_id,emp_name,age,gender,dept_id
    </sql>
select <include refid="empColumns"></include> from t_emp

总结:

动态SQL:
1. if 通过test属性中的表达式判断标签中的内容是否会拼接到SQL中
2.where
若where标签中有条件成立,会自动生成where关键字
会自动将where标签中的内容前多余的and去掉,但是其中内容后的and不能去掉
若where标签中没有任何一个条件成立,则where没有任何功能
3.trim
prefix、suffix:在标签中内容前面后面添加指定内容
prefixOverrides、suffixOverrides:在标签中内容前面后面去掉指定内容
4.choose、when、otherwise
相当于java中的if····else if···else
when至少有一个,otherwise做多设置一个
5.foreach
collection:设置需要循环的数组或者集合
item:用一个字符串表示数组或者集合中的每一个数据
separator:设置每次循环的数据之间的分隔符
open:循环的所有内容以什么开始
close:循环的所有内容以什么结束
6.sql片段
可以记录一段SQL,在需要使用的<include>
<sql id=“empColumns”>
emp_id,emp_name,age,gender,dept_id
</sql>
select <include refid=“empColumns”></include> from t_emp

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
*修正 +增加 -去除 ^调整 1.2.9 *修正查看我的表编辑、删除用户视图、存储过程、用户函数时列表为空时的报错; +在查看我的表增加导出表结构、索引、视图、存储过程、用户函数为SQL语句的功能。 1.2.8 ^允许修改密码处使用空密码,以方便一些要求空密码的软件连接; *修正win10下查询分析器缺少动态库和语法高亮未激活的问题; +增加了大容量数据的存取支持,增加bcp命令,允许在SQL使用bcp命令进行大数据的导入导出; +增加BULK INSERT、OPENROWSET这些数据批处理SQL命令的支持。 示例:--OPENROWSET SELECT CustomerID, CompanyName FROM OPENROWSET('Microsoft.Jet.OLEDB.4.0', 'C:\Program Files\Microsoft Office\OFFICE11\SAMPLES\Northwind.mdb'; 'admin';'',Customers); 这种通过OPENROWSET,把access,excell,cvs,txt都变成一个表来取。 示例:--BULK INSERT fmt由bcp生成 BULK INSERT xxxTable FROM 'c:\xxx.csv' WITH (FORMATFILE = 'fieldMap.fmt', BATCHSIZE=10000) 1.2.7 +配置添加Debug条件项,其值非0,则在启动时不会锁定面板,便于程序员使用; +计划任务备份部分增加对备份文件个数的定义,允许保留5~99个备份,旧的备份自动删除; +托盘区菜单添加“查找”项,用来快速打开程序所在目录,方便开启多个副本的用户查找对应目录; ^数据库页右键菜单启动事件探查器时,自动加载标准模板,方便使用。 1.2.6 *还原数据库时,修正输入库名时点取消后没有止还原等错误; +查询分析器添加语法高亮支持; *修正关闭服务时,有机率卡顿的现象,进行了优化处理; +在操作系统关闭时,自动停止服务,防止数据丢失。 1.2.5 +数据库页增加查看我的表功能菜单项,可管理视图、存储过程及自定义函数和查看表结构等; ^部分菜单及按钮增加图标,增加美观度; +内存管理页增加AWE开关,以解决部分电脑内存不足造成运行缓慢的问题,AWE功能也占内存。 1.2.4 ^选择开机启动时,会自动删除与软件关联的注册表项,防止变更实例名造成注册表残留,对于已登记开机启动,又直接删除了软件的,请手工删除注册表Run项的残留; *修正部分win7系统下无法正常解锁的问题(系统无法访问127.0.0.1造成); *修正部分文字描述内容错误(漏字或多打字等)。 1.2.3 +数据库页面,集成外部工具“查询分析器”与“事件探查器”,系SQL自带程序,方便使用; -删除内置“查询分析”功能页; ^数据库页面,密码修改,允许任意字符,不再限制只能为0~9a~z了,但不允许为空; ^数据库内核升级至8.00.2305,开启AWE,支持大内存(超2G)及修复漏洞; +增加SQL Tips页,记录一些常用的SQL语句,方便查阅; ^标题栏解锁界面和密码修改页面进行调整,增加多语言支持。 1.2.2 *附加数据库时,修正输入库名时点取消后没有止附加等错误; +增加面板锁,点击左上角的金锁,输入SA用户密码,输入正确则打开面板,否则隐藏面板,不限制开、关服务; +数据库页面,右键菜单增加打开文件目录,方便用户操作; +增加内存管理页,控制SQL Server内存占用,与企业管理器相同。 1.2.1 ^未开启服务时,关闭窗口会退出程序,开启服务时,关窗窗口则是隐藏; *附加数据库时,修正目标目录与源目录相同时无法附加的问题。 1.2.0 +增加托盘区菜单项“重启”,方便重启SQL服务; ^附加数据库文件时,将移动改为复制,原文件不会被删除; +计划任务在备份数据库后,自动清除旧备份,只保留最后5个备份(按文件,不按时间); *修正计划任务无法正确执行的问题,由皮肤引起的。 1.1.9 +增加win8的支持,增加皮肤以美化界面; +增加查询分析器,方便使用SQL操作数据库; +增加简体、繁体语言切换,方便港台及深圳用户使用。 1.1.8 ^计划任务执行SQL语句变更为执行SQL脚本文件,支持GO分隔,方便执行复杂任务。 1.1.7 +配置文件增加AppTitle字符串项,如果有输入内容,则在启动时会以该项的值为窗口标题;繁体用户请将配置文件保存为Unicode格式; *修正没有清除默认实
第1章 全局在胸——用工具对SQL整体优化 1 1.1 都有哪些性能工具 1 1.1.1 不同调优场景分析 2 1.1.2 不同场景对应工具 2 1.2 整体性能工具的要点 4 1.2.1 五大性能报告的获取 5 1.2.2 五大报告关注的要点 10 1.3 案例的分享与交流 18 1.3.1 和并行等待有关的案例 18 1.3.2 和热块竞争有关的案例 19 1.3.3 和日志等待有关的案例 20 1.3.4 新疆某系统的前台优化 20 1.3.5 浙江某系统的调优案例 21 1.4 本章总结延伸与习题 21 1.4.1 总结延伸 21 1.4.2 习题训练 23 第2章 风驰电掣——有效缩短SQL优化过程 24 2.1 SQL调优时间都去哪儿了 25 2.1.1 不善于批处理频频忙交互 25 2.1.2 无法抓住主要矛盾瞎折腾 25 2.1.3 未能明确需求目标白费劲 26 2.1.4 没有分析操作难度乱调优 26 2.2 如何缩短SQL调优时间 27 2.2.1 先获取有助调优的数据库整体信息 27 2.2.2 快速获取SQL运行台前信息 27 2.2.3 快速拿到SQL关联幕后信息 28 2.3 从案例看快速SQL调优 29 2.3.1 获取数据库整体的运行情况 29 2.3.2 获取SQL的各种详细信息 29 2.4 本章总结延伸与习题 32 2.4.1 总结延伸 32 2.4.2 习题训练 33 第3章 循规蹈矩——如何读懂SQL执行计划 34 3.1 执行计划分析概述 35 3.1.1 SQL执行计划是什么 35 3.1.2 统计信息用来做什么 36 3.1.3 数据库统计信息的收集 37 3.1.4 数据库的动态采样 37 3.1.5 获取执行计划的方法(6种武器) 40 3.2 读懂执行计划的关键 48 3.2.1 解释经典执行计划方法 49 3.2.2 总结说明 55 3.3 从案例辨别低效SQL 55 3.3.1 从执行计划读出效率 56 3.3.2 执行计划效率总结 60 3.4 本章习题、总结与延伸 60 第4章 运筹帷幄——左右SQL执行计划妙招 62 4.1 控制执行计划的方法综述 63 4.1.1 控制执行计划的意义 63 4.1.2 控制执行计划的思路 64 4.2 从案例探索其方法及意义 65 4.2.1 HINT的思路 65 4.2.2 非HINT方式的执行计划改变 72 4.2.3 执行计划的固定 100 4.3 本章习题、总结与延伸 102 第5章 且慢,感受体系结构让SQL飞 103 5.1 体系结构知识 104 5.1.1 组成 104 5.1.2 原理 104 5.1.3 体会 105 5.2 体系与SQL优化 106 5.2.1 与共享池相关 107 5.2.2 数据缓冲相关 111 5.2.3 日志归档相关 116 5.3 扩展优化案例 118 5.3.1 与共享池相关 118 5.3.2 数据缓冲相关 122 5.3.3 日志归档相关 126 5.4 本章习题、总结与延伸 130 第6章 且慢,体验逻辑结构让SQL飞 132 6.1 逻辑结构 132 6.2 体系细节与SQL优化 133 6.2.1 Block 133 6.2.2 Segment与extent 137 6.2.3 Tablespace 139 6.2.4 rowid 139 6.3 相关优化案例分析 140 6.3.1 块的相关案例 141 6.3.2 段的相关案例 144 6.3.3 表空间的案例 148 6.3.4 rowid 151 6.4 本章习题、总结与延伸 153 第7章 且慢,探寻表的设计让SQL飞 154 7.1 表设计 154 7.1.1 表的设计 155 7.1.2 其他补充 155 7.2 表设计与SQL优化 156 7.2.1 表的设计 156 7.2.2 其他补充 179 7.3 相关优化案例分析 184 7.3.1 分区表相关案例 185 7.3.2 全局临时表案例 190 7.3.3 监控异常的表设计 195 7.3.4 表设计优化相关案例总结 199 7.4 本章习题、总结与延伸 199 第8章 且慢,学习索引如何让SQL飞 200 8.1 索引知识要点概述 201 8.1.1 索引结构的推理 201 8.1.2 索引特性的提炼 204 8.2 索引的SQL优化 206 8.2.1 经典三大特性 207 8.2.2 组合索引选用 217 8.2.3 索引扫描类型的分类与构造 219 8.3 索引相关优化案例 225 8.3.1 三大特性的相关案例 225 8.3.2 组合索引的经典案例 231 8.4 本章习题、总结与延伸 234 第9章 且慢,弄清索引之阻碍让SQL飞 23

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值