当前位置: 首页 > news >正文

数据库之SQL(二)

目录

一、简述SQL中如何将“行”转换为“列”

二、简述SQL注入

三、如何将一张表的部分数据更新到另一张表

四、WHERE和HAVING的区别


一、简述SQL中如何将“行”转换为“列”

        我们以MySQL数据库为例,来说明行转列的实现方式。

        首先,假设我们有一张分数表(tb_score),表中的数据如下图:

        然后,我们再来看一下转换之后需要得到的结果,如下图:

        可以看出,这里行转列是将原来的subject字段的多行内容选出来,作为结果集中的不同列,并根据userid进行分组显示对应的score。通常,我们有两种方式来实现这种转换。

        1、使用 CASE...WHEN...THEN 语句实现行转列,参考如下代码:

SELECT userid,
SUM(CASE `subject` WHEN '语文' THEN score ELSE 0 END) as '语文',
SUM(CASE `subject` WHEN '数学' THEN score ELSE 0 END) as '数学',
SUM(CASE `subject` WHEN '英语' THEN score ELSE 0 END) as '英语',
SUM(CASE `subject` WHEN '政治' THEN score ELSE 0 END) as '政治'
FROM tb_score
GROUP BY useri

        注意,SUM() 是为了能够使用GROUP BY根据userid进行分组,因为每一个userid对应的subject="语文"的记录只有一条,所以SUM() 的值就等于对应那一条记录的score的值。假如userid='001' and subject='语文' 的记录有两条,则此时SUM() 的值将会是这两条记录的和,同理,使用Max()的值将会是这两条记录里面值最大的一个。但是正常情况下,一个user对应一个subject只有一个分数,因此可以使用SUM()、MAX()、MIN()、AVG()等聚合函数都可以达到行转列的效果。

        2、使用 IF() 函数实现行转列,参考如下代码:

SELECT userid,
SUM(IF(`subject`='语文',score,0)) as '语文',
SUM(IF(`subject`='数学',score,0)) as '数学',
SUM(IF(`subject`='英语',score,0)) as '英语',
SUM(IF(`subject`='政治',score,0)) as '政治'
FROM tb_score
GROUP BY userid

        注意, IF(subject='语文',score,0) 作为条件,即对所有subject='语文'的记录的score字段进行SUM()、MAX()、MIN()、AVG()操作,如果score没有值则默认为0。

二、简述SQL注入

        SQL注入的原理是将SQL代码伪装到输入参数中,传递到服务器解析并执行的一种攻击手法。也就是说,在一些对SERVER端发起的请求参数中植入一些SQL代码,SERVER端在执行SQL操作时,会拼接对应参数,同时也将一些SQL注入攻击的“SQL”拼接起来,导致会执行一些预期之外的操作。

        举个例子:

        比如我们的登录功能,其登录界面包括用户名和密码输入框以及提交按钮,登录时需要输入用户名和密码,然后提交。此时调用接口/user/login/ 加上参数username、password,首先连接数据库,然后后台对请求参数中携带的用户名、密码进行参数校验,即SQL的查询过程。假设正确的用户名和密码为ls和123456,输入正确的用户名和密码、提交,相当于调用了以下的SQL语句。

SELECT * FROM user WHERE username = 'ls' AND password = '123456'

        SQL中会将#及--以后的字符串当做注释处理,如果我们使用 ' or 1=1 # 作为用户名参数,那么服务端构建的SQL语句就如下:

select * from user where username='' or 1=1 #' and password='123456'

        而#会忽略后面的语句,而1=1属于常等型条件,因此这个SQL将查询出所有的登录用户。其实上面的SQL注入只是在参数层面做了些手脚,如果是引入了一些功能性的SQL那就更危险了,比如上面的登录功能,如果用户名使用这个 ' or 1=1;delete * from users; # ,那么在";"之后相当于是另外一条新的SQL,这个SQL是删除全表,是非常危险的操作,因此SQL注入这种还是需要特别注意的。

        如何解决SQL注入?

        1、严格的参数校验。参数校验就没得说了,在一些不该有特殊字符的参数中提前进行特殊字符校验即可。

        2、SQL预编译。在知道了SQL注入的原理之后,我们同样也了解到MySQL有预编译的功能,指的是在服务器启动时,MySQL Client把SQL语句的模板(变量采用占位符进行占位)发送给MySQL服务器,MySQL 服务器对SQL语句的模板进行编译,编译之后根据语句的优化分析对相应的索引进行优化,在最终绑定参数时把相应的参数传送给MySQL服务器,直接进行执行,节省了SQL查询时间,以及MySQL服务器的资源,达到一次编译、多次执行的目的,除此之外,还可以防止SQL注入。

        具体是怎样防止SQL注入的呢?实际上当将绑定的参数传到MySQL服务器,MySQL服务器对参数进行编译,即填充到相应的占位符的过程中,做了转义操作。我们常用的JDBC就有预编译功能,不仅提升性能,而且防止SQL注入。

三、如何将一张表的部分数据更新到另一张表

        可以采用关联更新的方式,将一张表的数据更新到另一张表内。参考下面代码:

update b set b.col=a.col from a,b where a.id=b.id;
update b set col=a.col from b inner join a on a.id=b.id;
update b set b.col=a.col from b left join a on b.id=a.id;

四、WHERE和HAVING的区别

        WHERE:WHERE是一个约束声明,使用WHERE约束来自数据库的数据,WHERE是在结果返回之前起作用的,WHERE中不能使用聚合函数。

        HAVING:HAVING是一个过滤声明,是在查询返回结果集以后对查询结果进行的过滤操作,在HAVING中可以使用聚合函数。另一方面,HAVING子句中不能使用除了分组字段和聚合函数之外的其他字段。

        从性能的角度来说,HAVING子句中如果使用了分组字段作为过滤条件,应该替换成WHERE子句。因为WHERE可以在执行分组操作和计算聚合函数之前过滤掉不需要的数据,性能会更好。

相关文章:

  • uniapp实现图片懒加载 封装组件
  • qt QTreeWidget文件管理器拖入应用,从应用拖入文件管理器拷贝
  • VMware中的三种虚拟网络模式
  • 交换机基本原理
  • 使用 Selenium 实现自动化分页处理与信息提取
  • docker容器技术、k8s的原理和常见命令、用k8s部署应用步骤
  • 【安全攻防】网络安全中的序列化与反序列
  • 深入理解C# log4Net日志框架:功能、使用方法与性能优势
  • InfluxDB时序数据库基本使用介绍
  • Java集成openai,ollama,千帆,通义千问实现文本聊天
  • 开发者工具攻略:前端测试的极简指南
  • 刚办理的手机号被停用,你可能遇到这些问题了!
  • 多态的优点
  • R语言进行字符的替换和删减gsub,substr函数
  • vue3中若v-model绑定的响应字段出现三级,该如何实现rules验证规则
  • [ 一起学React系列 -- 8 ] React中的文件上传
  • 「译」Node.js Streams 基础
  • 【React系列】如何构建React应用程序
  • 【vuex入门系列02】mutation接收单个参数和多个参数
  • 2017-09-12 前端日报
  • Android框架之Volley
  • chrome扩展demo1-小时钟
  • css系列之关于字体的事
  • HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
  • Laravel深入学习6 - 应用体系结构:解耦事件处理器
  • PAT A1092
  • React中的“虫洞”——Context
  • Vue.js源码(2):初探List Rendering
  • 阿里云容器服务区块链解决方案全新升级 支持Hyperledger Fabric v1.1
  • 爱情 北京女病人
  • 编写高质量JavaScript代码之并发
  • 第十八天-企业应用架构模式-基本模式
  • 服务器之间,相同帐号,实现免密钥登录
  • 构建二叉树进行数值数组的去重及优化
  • 诡异!React stopPropagation失灵
  • 利用DataURL技术在网页上显示图片
  • 聊聊redis的数据结构的应用
  • 聊聊springcloud的EurekaClientAutoConfiguration
  • 面试题:给你个id,去拿到name,多叉树遍历
  • 使用Envoy 作Sidecar Proxy的微服务模式-4.Prometheus的指标收集
  • 使用阿里云发布分布式网站,开发时候应该注意什么?
  • 推荐一个React的管理后台框架
  • 一道面试题引发的“血案”
  • 白色的风信子
  • #if #elif #endif
  • #include
  • #include<初见C语言之指针(5)>
  • #pragam once 和 #ifndef 预编译头
  • $(selector).each()和$.each()的区别
  • (ZT)北大教授朱青生给学生的一封信:大学,更是一个科学的保证
  • (强烈推荐)移动端音视频从零到上手(下)
  • (一)utf8mb4_general_ci 和 utf8mb4_unicode_ci 适用排序和比较规则场景
  • (一)为什么要选择C++
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (转) 深度模型优化性能 调参