SQL 基础语法


SQL 基础语法

SQL 概述

结构化查询语言(Structured Query Language)简称 SQL,是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统。

什么是数据库

数据库专业的来说,其实就是一种电子的仓库,是专门储存数据和管理管理数据的一种处所,用户可以对数据库中的数据进行新增和更新或者删除等操作。数据库(database)是保存有组织的数据的容器

Mysql 基本概念

MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL 是最好的 RDBMS (Relational Database Management System,关系数据库管理系统)

数据库表的理解

  1. 数据库中最基本的单元是表 table,数据库中以 table 的形式表示数据
  2. 任何一张表都有行和列:
    • 行(row):被称为数据/记录
    • 列(column):被称为字段
      • 字段包含,字段名、数据类型、约束等属性
      • 字段名可以理解是一个普通的名称,命名尽量做到见名知意
      • 数据类型:子字符串、数字、日期等
      • 约束:约束也有很多,其中一个叫做唯一约束,唯一约束添加后,该字段的数据值不能够重复

SQL 语句分类

  • DQL:数据库查询语言(凡是带有 select 关键字的都是查询语句)
    • select...
  • DML:数据库操作语言(凡是对表中的数据进行增删改都是 DML)
    • insert 增
    • delete 删
    • update 改
  • DDL:数据定义语言,凡是带有 create、drop、alter 的都是 DDL, DDL 主要操作的是表结构的增删改
    • create 新建、等同于增
    • drop 删除
    • alter 修改
  • TCL:事务控制语言,包含如下内容:
    • 事务提交 commit
    • 事务回滚 rollback
  • DCL:数据控制语言
    • 授权 grant
    • 撤销权限 revoke...

SQL 编写

对于 SQL 语句来说,都是通用的,所有的 SQL 语句以;结尾,SQL 语句不区分大小写

注意:所有数据库中,字符串统一使用单引号括起来,单引号是标准的,双引号在 oracle 数据库中用不了,但是可以在 mysql 中使用

简单查询

  1. 查询一个字段:SELECT 字段名 FROM 表名; SELECT 和 from 关键字,字段名和表名都是标识符
SELECT name FROM demo;
  1. 查询两个字段:SELECT 字段名1,字段名2 FROM 表名; 多个字段用,分割
SELECT name,id FROM demo;
  1. 查询全部
    • 第一种方式:把每个字段都写上SELECT a,b,c,d,e,f,g FROM 表名;
    • 第二种方式:SELECT * FROM 表名; 不推荐,执行效率低,可读性比较差
  2. 起别名进行查询 使用as关键字起别名 SELECT 字段名 as 别名 FROM 表名; 注意只是将显示的查询结果,使用别名进行显示,原表字段名不会进行修改
    SELECT name as nameId FROM demo;
    
    • 可以通过空格的形式省略 as 关键字
    SELECT name nameId FROM demo;
    
    • 起别名,别名中间不允许添加空格,如果一定要加空格别名使用单引号或者双引号引起来
    SELECT name as 'name Id' FROM demo;
    
  3. 查询表字段DESC 表名
  4. 查询员工姓名和员工对应的 12 个月的薪资,起别名显示查询结果
SELECT name,wages*12 as yearwages FROM demo;

条件查询

条件查询需要用到 where 语句,where 必须放到 from 语句表的后面,支持如下运算符

运算符说明
= 等于
<>!=不等于
> 大于
< 小于
>=大于等于
<=小于等于
BETWEEN...AND...两个值之间,等同于 >= and <= BETWEEN...AND...需要遵循左小右大,闭区间,包含左大右小
is null为 null(is not null 不为空)
and并且
or或者
in包含,相当于多个 or(not in 不在这个范围中)
likelike 称为模糊查询,支持%_下划线匹配,%匹配任意个字符,下划线,一个下划线只能匹配一个字符

基础语法:SELECT 查询列表 FROM 表名 WHERE 筛选表达式;

/*等于:查询年龄为20岁的人员*/
SELECT name,age FROM demo WHERE age = 20;

/*不等:查询年龄不为20岁的人员*/
SELECT name,age FROM demo WHERE age != 20;

/*不等:查询年龄不为20岁的人员*/
SELECT name,age FROM demo WHERE age <> 20;

/*小于:查询年龄小于20岁的人员*/
SELECT name,age FROM demo WHERE age < 20;

/*小于等于:查询年龄小于等于20岁的人员*/
SELECT name,age FROM demo WHERE age <= 20;

/*大于:查询年龄小于20岁的人员*/
SELECT name,age FROM demo WHERE age > 20;

/*大于等于:查询年龄大于等于20岁的人员*/
SELECT name,age FROM demo WHERE age >= 20;

/*两个值之间:查询年龄大于等于20岁小于等于30岁的人员*/
SELECT name,age FROM demo WHERE age >= 20 and age <= 30;

/*两个值之间:查询年龄大于等于20岁小于等于30岁的人员*/
SELECT name,age FROM demo WHERE age BETWEEN 20 and 30;

/*is null查询为空:查询数据库中 email 邮箱字段值为空的人员*/
SELECT name,age,email FROM demo WHERE email is null;

/*is not null查询不为空:查询数据库中 email 邮箱字段值不为空的人员*/
SELECT name,age,email FROM demo WHERE email is not null;

/*and并且:查询数据库中 email 邮箱字段值为空且年龄等于28岁的人员*/
SELECT name,age,email FROM demo WHERE age = 28 and email is null;

/*or或者:查询数据库中 age 字段值为28或者age值为20的人员*/
SELECT name,age,email FROM demo WHERE age = 28 or age = 20;

/* and 和 or 同时出现优先级问题,and 优先级比 or 高,先执行 and 后执行 or,如需先执行or需要使用小括号括起来 */
SELECT name,age,sex FROM demo WHERE sex = 2 and (age = 26 or age > 35);

/* in相当于多个or查询,查询age值为20和38的 */
SELECT name,age,sex FROM demo WHERE age in(20, 38);

/* not in相当于多个or查询,查询age值不为20和38的 */
SELECT name,age,sex FROM demo WHERE age not in(20, 38);

/*like模糊查询:查找名字中包含zh的 % 匹配任意个字符*/
SELECT name,age FROM demo WHERE name LIKE '%zh%';

/*like模糊查询:查找名字中以ao结尾的 % 匹配任意个字符*/
SELECT name,age FROM demo WHERE name LIKE '%ao';

/*like模糊查询:查找名字中以d开头的 % 匹配任意个字符*/
SELECT name,age FROM demo WHERE name LIKE 'd%';

/*like模糊查询:查找名字中第二个字母是c的 % 匹配任意个字符*/
SELECT name,age FROM demo WHERE name LIKE '_c%';

/*like模糊查询:查找名字中第三个字母是o的 % 匹配任意个字符*/
SELECT name,age FROM demo WHERE name LIKE '__o%';

/*like模糊查询:查找名字中包含下划线的,使用转义符*/
SELECT name,age FROM demo WHERE name LIKE '%\_%';

注意事项:

  1. 所有数据库中,字符串统一使用单引号括起来
  2. and 和 or 同时出现优先级问题,and 优先级比 or 高,先执行 and 后执行 or,如需先执行 or 需要使用小括号括起来
  3. in 不是一个区间,in 后面跟的是具体的值,找出符合具体条件值的
  4. 如果在模糊查询匹配数据时数据中存在特殊字符比如下划线可以使用转义符\进行转换

排序数据

排序采用 order by 子语句,order by 后面跟上排序字段,排序字段可以放多个使用逗号分割,order by 默认采用升序,如果存在 where 子语句那么 order by 必须放到 where 语句的后面

  1. 单一字段排序
    • order by 默认采用升序 asc
    • order by 如果需要按照升序进行排列,需要添加 desc 关键字
/*默认升序*/
SELECT name,age FROM demo ORDER BY age;
/*使用 desc 关键字进行降序*/
SELECT name,age FROM demo ORDER BY age DESC;
  1. 多个字段排序

查询人员名字和薪资,按照年龄进行升序排序,如果年龄一样,按照姓名升序排序

/*age在前,起主导作用,只有age相等,采用使用 nane进行排序*/
SELECT name,age FROM demo ORDER BY age ASC, name ASC;
  1. 使用字段的位置排序,不推荐实际开发中使用,列顺序发生改变后,对应列数字 2 可能失效
/*按照查询结果的第二列进行排序 第二列为age*/
SELECT name,age FROM demo ORDER BY 2;
  1. 案例:找出年龄在 20 岁到 30 岁之间的员工信息,按照年龄进行降序排序
/*第一种写法*/
SELECT name,age,email FROM demo WHERE age >= 20 and age <= 30 ORDER BY age DESC;

/*第二种写法*/
SELECT name,age,email FROM demo WHERE age BETWEEN 20 and 30 ORDER BY age DESC;

数据处理函数/单行处理函数

单行处理函数的特点:一个输入对应一个输出,和单行处理函数相对应的是多行处理函数,多行处理函数多个输入,对应一个输出

函数说明
LOWER()将字符串转换为小写
UPPER()将字符串转换为大写
LEFT()返回字符串左边的字符
LENGTH()返回字符串的长度
TRIM()去字符串前后空格
LTRIM()去掉字符串左边的空格
RIGHT()返回字符串右边的字符
RTRIM()去掉字符串左边的空格
SUBSTR()取子串(SUBSTR(被截取的字符串,起始下标(从 1 开始),截取的长度))
SUBSTRING()提取字符串的组成部分
concat()字符串拼接
SOUNDEX()返回字符串的 SOUNDEX 值(听起来读音相似)
str_to_date()将字符串转换成日期
date_format()格式化日期
format()设置千分位
round()四舍五入
rand()生成随机数
ifnull()可以将 null 转换成一个具体值,在数据库中,只要有 null 参与的数学运算,最终结果就是 null,所以可以使用 ifnull() 进行计算
ABS()返回绝对值
COS()返回一个角度的余弦
EXP()返回一个数的指数
PI()返回圆周率 π 的值
SIN()返回一个角度的正弦
SQRT()返回一个数的平方根
TAN()返回一个角度的正切
case...when..then..when...then...else..end如果 xxx 满足则执行什么,如果 xxx 则执行什么,否则按照原来的

/*LOWER转换成小写*/
SELECT id,LOWER(name) as low_name from demo;

/*UPPER转换成小写*/
SELECT id,UPPER(name) as upp_name from demo;

/*TRIM去除前后空格*/
SELECT id,TRIM(name) as trim_name from demo;

/*concat拼接字符串*/
select id,concat(name,age) as cont_name from demo;

/*SUBSTR字符串截取*/
select id, SUBSTR(name,1,2) as substr_name from demo;

/*round四舍五入:保留1位小数*/
select round(1226.2568, 1) as result from demo;

/*round四舍五入:保留2位小数*/
select round(1226.2568, 2) as result from demo;

/*round四舍五入:保留到10位*/
select round(1226.2568, -1) as result from demo;

/*rand生成100以内随机数*/
select round(rand() * 100, 0) as result from demo;

/*ifnull可以将 null转成一个具体值,解决只要有null参与计算结果为null的问题*/
select name,ifnull(age,sex) as age_sex from demo;

/*case...when..then..when...then...else..end
当年龄为25工资上调10%,为26工资上调50%,只查询年龄为25或者26的
相当于 javaScript中的 if else
*/
select name,age,salary_money from demo;

select
	name,
	age,
	salary_money,
	(case age when '25' then salary_money*1.1 when '26' then salary_money*1.5 else salary_money end) as new_money
from
	demo
WHERE
	age = 26 or age = 25;

分组函数/聚合函数/多行处理函数

多行处理函数特点:输入多行,最终输出一行,可用统计

注意:

  1. 分组函数在使用的时候必须先进行分组,然后才能用
  2. 如果没有对数据进行分组,整张表默认为一组
  3. 分组函数自动东忽略 null,不需要提前对 null 进行处理
  4. 分组函数中 count(*)count(具体字段)

多行处理函数一共有五个:count 计数、sum 求和、avg 平均值、max 最大值、min 最小值


/*count计数,默认分组一张表一组*/
select name,age,count(salary_money) from demo;

/*sum求和*/
select name,sum(age),sum(salary_money) from demo;

/*avg平均值*/
select name,avg(salary_money) as avg_result from demo;

/*max最大值*/
select name,max(salary_money) as max_money from demo;

/*min最小值*/
select name,min(salary_money) as min_money from demo;

分组查询

什么是分组查询?

在实际应用中,可能有这样的需求,需要先进行分组,然后对每一组数据进行操作,这个时候我们需要使用分组查询 语法

SELECT ... FROM ... GROUN BY ...

应用场景 计算每个部门的工资和? 计算每个工作岗位工资的平均薪资? 找出每个工作岗位的最高薪资?

之前的关键字全部组合,执行顺序如下

SELECT ... FROM ... WHERE ... GROUN BY ... ORDER BY...

执行顺序如下:

  1. SELECT
  2. FROM
  3. WHERE
  4. GROUN BY
  5. ORDER BY

结论

在一条 select 语句中,如果有 group by 语句的话,select 后面只能跟:参加分组的字段,以及分组函数,其他一律不能跟

/*按照年龄进行分,然后对工资进行求和
先从 demo 表中查询数据,根据job字段进行分组,然后对每一组数据进行
sum(salary_money)
*/
SELECT job,sum(salary_money) as total_money FROM demo GROUP BY job;

/*每个岗位最高信息*/
SELECT job,max(salary_money) as total_money FROM demo GROUP BY job;

/*使用HAVING 可以对芬湾族之后的数据进行进一步的过滤, HAVING不能单独使用,
HAVING不代替 WHERE ,HAVING 必须和GROUP BY一起使用
以下语句执行效率较低:
*/
SELECT job,max(salary_money) as total_money FROM demo GROUP BY job HAVING max(salary_money) > 5500;

/*有过滤条件的优先使用 WHERE 语句设置条件后,再进行分组
WHERE 和 HAVING youxian 优先使用 WHERE
*/
SELECT job,salary_money FROM demo WHERE salary_money > 3000 GROUP BY job;

/*找出不同岗位的平均薪资,要求显示平均薪资高于6000的,
1. 找出每个岗位平均薪资
*/
SELECT job, AVG(salary_money) FROM demo GROUP BY job;
/*2.找出不同岗位的平均薪资,要求显示平均薪资高于6000的 */
SELECT job,AVG(salary_money) FROM demo GROUP BY job HAVING AVG(salary_money) > 6000;

总结(单表查询)

  1. 单表查询关键字执行顺序如下,不能颠倒 select ... from ... where ... group by ... having ... order by
  2. 案例:找出每个岗位的平均薪资,要求平均薪资大于 5000 的,除了音频岗位之外,要求按照平均薪资降序排列
SELECT job,AVG(salary_money) as svg_money FROM demo WHERE job <> '音频' GROUP BY job HAVING AVG(salary_money) > 5000 ORDER BY svg_money DESC;

去除重复数据

/*查询结果去重,关键字DISTINCT*/
SELECT DISTINCT job FROM demo;

/* 查询结果去重,关键字DISTINCT 如果 DISTINCT 出现在两个字段之间,表示两个字段联合起来去重*/
SELECT DISTINCT job,sex FROM demo WHERE sex IS NOT null;

/*统计工作岗位的数量*/
SELECT COUNT(DISTINCT job) as total_number FROM demo;

连接查询/连表查询

连接查询:也可以叫跨表查询,需要关联多个表进行查询


子查询


约束


索引

事务

锁机制

设计数据库表

性能优化

数据库设计工具