后端SQL语句问题总结(一)

       本文章是关于本人在一次项目开发过程中遇到SQL语句的问题总结,并不全面,之后遇到新问题的会继续更新。

1、 ${}和#{}的区别

后端使用SQL语句时注意${}和#{}的区别,使用#{}可以防止SQL注入的问题,#{}是占位符(会自动加引号),${}是拼接符(需要自己加引号)。

如果你所传的参数是String类型,你在sql语句中使用${}就需要在外面加上单引号(双引号都行)。

表名作为变量时,必须使用${},当表名带有汉字时要用反引号``。

在后端开发中我使用了两次表名的动态变化

一次是动态改变表名插入数据

@Insert("INSERT INTO ${tablename}(id, name, signintime, state, subject) VALUES(#{id}, #{name}, #{signintime}, #{state}, #{subject})")

另一次是动态改变表名查询数据(使用了左连接)

@Select("SELECT  l.id, l.name, s.state , s.signintime FROM  login l LEFT JOIN `${tablename}` s ON l.id = s.id AND l.sclass = #{sclass} AND s.subject = #{subject} AND s.signintime = #{signintime}")

两条语句对比,发现在插入语句中我的表名没有加反引号,但在查询语句中表明上加上了反引号,我个人判断应该是SQL语句识别的问题,不过为了安全我建议都加上反引号,确保能正确识别。

2、@Param注解

当使用了@Param注解来声明参数的时候,SQL语句取值使用#{},${}取值都可以。

当不使用@Param注解声明参数的时候,必须使用的是#{}来取参数。使用${}方式取值会报错。

不使用@Param注解时,参数只能有一个,并且是Javabean(实体类)。在SQL语句里可以引用JavaBean的属性,而且只能引用JavaBean的属性。

注意依赖包为:

import org.apache.ibatis.annotations.Param;

与@Param相关的有三个,具体的区别不太清楚,上述依赖包是在SpringBoot框架下引入的

3多表查询

2.3.1 内连接查询(INNER JOIN)

内连接查询返回两个表中满足连接条件的记录。如果某个记录在另一个表中没有匹配项,则不会出现在结果集中。

示例:查询学生表(students)和成绩表(scores)中,学生的姓名和对应的成绩。

SELECT students.name, scores.score

FROM students

INNER JOIN scores ON students.id = scores.student_id;

2.3.2左连接查询(LEFT JOIN 或 LEFT OUTER JOIN)

左连接查询返回左表中的所有记录和右表中满足连接条件的记录。如果左表中的某条记录在右表中没有匹配项,则结果集中右表的部分会显示为NULL。

示例:查询所有学生及其成绩,即使某些学生没有成绩。

SELECT students.name, scores.score

FROM students

LEFT JOIN scores ON students.id = scores.student_id;

2.3.3 右连接查询(RIGHT JOIN 或 RIGHT OUTER JOIN)

右连接查询返回右表中的所有记录和左表中满足连接条件的记录。如果右表中的某条记录在左表中没有匹配项,则结果集中左表的部分会显示为NULL。

示例:查询所有成绩及其对应的学生姓名,即使某些成绩没有对应的学生。

SELECT students.name, scores.score

FROM students

RIGHT JOIN scores ON students.id = scores.student_id;

我刚开始使用时在on后添加了两个表关联的判断条件后,继续使用了where连接其他的判断条件,发现了查询后的结果与预期不符,将where改为and连接后查询出正确解决。

注意SQL查询时使用,占位符的个数要与你方法中传入的参数个数一致

如下方

//sclasss参数使用了两次,但是只有一个,在运行时会报错
@Select("SELECT  l.id, l.name, s.state , s.signintime FROM  login l LEFT JOIN `${slass}` s ON l.id = s.id AND l.sclass = #{sclass} AND s.subject = #{subject} AND s.signintime = #{signintime}")
List<Result> findStudentAll(@Param("sclass") String sclass, @Param("subject") String subjecte ,@Param("signintime") String signintime);



//将第一个sclass改为tablename,并在方法中新增一个tablename参数
@Select("SELECT  l.id, l.name, s.state , s.signintime FROM  login l LEFT JOIN `${tablename}` s ON l.id = s.id AND l.sclass = #{sclass} AND s.subject = #{subject} AND s.signintime = #{signintime}")
List<Result> findStudentAll(@Param("tablename") String tablename,@Param("sclass") String sclass, @Param("subject") String subjecte ,@Param("signintime") String signintime);

4、SQL语句调试

在SpringBoot的配置文件application.properties文件中增加以下配置

logging.level.项目路径(com.xxx.Mapper)=debug
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

可以在控制台输出SQL语句执行时的插入的数据和执行情况

如下:

//表示执行的SQL语句,之前的占位符用?代替,个人信息用xxxxx代替
Preparing: SELECT l.id, l.name, s.state , s.signintime FROM login l LEFT JOIN `软件2130` s ON l.id = s.id AND l.sclass = ? AND s.subject = ? AND s.signintime = ?
//按顺序对应查询条件
==> Parameters: xxxxxx(String), SpringBoot(String), 2024-06-18(String)
//查询结果
<==    Columns: id, name, state, signintime
<==        Row: xxxxxxxx, xxx, null, null
<==        Row: xxxxxxxx, xxx, null, null
<==        Row: xxxxxxxx, xxx, null, null
<==        Row: xxxxxxxx, xxx, 已签到, 2024-06-18
<==        Row: xxxxxxxx, 张三, null, null
<==        Row: xxxxxxxx, 李四, null, null
<==      Total: 6

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值