MySQL总结笔记

一.数据库概述 

 MySQL是一个开放源代码的关系型数据库管理系统

二.MySQL下载,安装,配置

2.1软件的下载:

下载地址:官网MySQL

2.2MySQL8.0环境变量配置

root用户密码忘记,重置的操作

三.SQL语言的规则与规范

3.1基本规则

  • SQL可以写在一行或者多行,为了提高可读性,各子句分行写,必要时使用缩进
  • 每条命令必须以";"或"\g"或"\G"结束
  • 关键字不能被缩写也不能分行
  • 标点符号:1)必须保证所有的(),单引号,双引号是成对结束的

                         2)必须使用英语状态下的半角输入方式

                         3)字符串型和日期时间类型的数据可以使用单引号(‘’)表示

                         4)列的别名,尽量使用(“”),而且不建议省略as

3.2SQL大小写规范

  • MySQL在Windows环境下大小写不敏感
  • MySQL在Linux环境下大小写敏感(入乡随俗)
  • 书写规范:数据库名,表名,表别名,字段别名都小写

                         SQL关键字,函数名,绑定变量都大写

3.3SQL的分类

DDL:数据定义语言  CREAT \ ALTER \ DROP \ RENAME \ TRUNCATE 

DML:数据操作语言 INSERT \ DELETE \ UPDATE \ SELECT

DCL:数据控制语言  COMMIT  \  ROLLBACK  \  SAVEPOINT  \  GRANT  \  REVOKE 

3.4注释

3.5导入现有的数据表,表的数据

方式一:命令行:source 文件的全路径名

方式二:基于具体的图形化界面的工具可以导入数据

四.基本的SELECT语句

4.0SELECT....

SELECT 9/2; #没有任何子句

4.1 SELECT ... FROM

SELECT   标识选择哪些列
FROM     标识从哪个表中选择

选择全部列:

SELECT *
FROM   employees;

4.2 列的别名

  • 紧跟列名,也可以在列名和别名之间加入关键字AS,别名使用双引号,以便在别名中包含空格或特殊的字符并区分大小写。

  • AS 可以省略,全称:alias

4.3 去除重复行

SELECT DISTINCT department_id
FROM   employees;

 4.4 空值参与运算

这里你一定要注意,在 MySQL 里面, 空值不等于空字符串。一个空字符串的长度是 0,而一个空值的长度是空。而且,在 MySQL 里面,空值是占用空间的。

null不等同于0,‘’,‘null’

空值参与运算:所有运算符或列值遇到null值,运算的结果都为null

4.5 着重号

我们需要保证表中的字段、表名等没有和保留字、数据库系统或常用方法冲突。如果真的相同,请在SQL语句中使用一对``(着重号)引起来。

4.6 查询常数

SELECT 查询还可以对常数进行查询。对的,就是在 SELECT 查询结果中增加一列固定的常数列。这列的取值是我们指定的,而不是从数据表中动态取出的。

你可能会问为什么我们还要对常数进行查询呢?

SQL 中的 SELECT 语法的确提供了这个功能,一般来说我们只从一个表中查询数据,通常不需要增加一个固定的常数列,但如果我们想整合不同的数据源,用常数列作为这个表的标记,就需要查询常数。

比如说,我们想对 employees 数据表中的员工姓名进行查询,同时增加一列字段corporation,这个字段固定值为“尚硅谷”,可以这样写:

SELECT '尚硅谷' as corporation, last_name FROM employees;

4.7.显示表结构

DESCRIBE employees;
DESC employees;

4.8.过滤数据

SELECT 字段1,字段2
FROM 表名
WHERE 过滤条件

五.运算符

5.1. 算术运算符

  • 在Java中,+的左右两边如果有字符串,那么表示字符串的拼接。但是在MySQL中+只表示数值相加。如果遇到非数值类型,先尝试转成数值,如果转失败,就按0计算。(补充:MySQL中字符串拼接要使用字符串函数CONCAT()实现)

  • 一个数除以整数后,不管是否能除尽,结果都为一个浮点数;

  • 一个数除以另一个数,除不尽时,结果为一个浮点数,并保留到小数点后4位;

  • 在数学运算中,0不能用作除数,在MySQL中,一个数除以0为NULL。

  • 取模运算结果正负与被模数一样

5.2. 比较运算符

  • 如果等号两边的值、字符串或表达式都为字符串,则MySQL会按照字符串进行比较,其比较的是每个字符串中字符的ANSI编码是否相等。

  • 如果等号两边的值都是整数,则MySQL会按照整数来比较两个值的大小。

  • 如果等号两边的值一个是整数,另一个是字符串,则MySQL会将字符串转化为数字进行比较。

  • 如果等号两边的值、字符串或表达式中有一个为NULL,则比较结果为NULL。

 关键字比较

LIKE运算符:

“%”:匹配0个或多个字符。

“_”:只能匹配一个字符。

SELECT	first_name
FROM 	employees
WHERE	first_name LIKE 'S%';

 REGEXP运算符用来匹配字符串,语法格式为:expr REGEXP 匹配条件。如果expr满足匹配条件,返回1;如果不满足,则返回0。若expr或匹配条件任意一个为NULL,则结果为NULL。

5.3. 逻辑运算符

OR可以和AND一起使用,但是在使用时要注意两者的优先级,由于AND的优先级高于OR,因此先对AND两边的操作数进行操作,再与OR中的操作数结合。

5.4. 位运算符

 

六.排序与分页

6.1. 排序数据

默认情况下,查询返回的数据是按照添加数据的顺序显示的

6.1.1 排序规则

使用 ORDER BY 子句排序

  • ASC(ascend): 升序

  • DESC(descend):降序

ORDER BY子句在SELECT语句的结尾

SELECT   last_name, job_id, department_id, hire_date
FROM     employees
ORDER BY hire_date ;

SELECT   last_name, job_id, department_id, hire_date
FROM     employees
ORDER BY hire_date DESC ;

ORDER BY后面如果没有关键字,默认升序

列的别名只能在ORDER BY中使用,不能在WHERE中使用

二级排序:

SELECT last_name, department_id, salary
FROM   employees
ORDER BY department_id, salary DESC;

在对多列进行排序的时候,首先排序的第一列必须有相同的列值,才会对第二列进行排序。如果第一列数据中所有值都是唯一的,将不再对第二列进行排序。

6.2分页

MySQL中使用 LIMIT 实现分页

LIMIT [位置偏移量,] 行数

MySQL 8.0中可以使用“LIMIT 3 OFFSET 4”,意思是获取从第5条记录开始后面的3条记录,和“LIMIT 4,3;”返回的结果相同。

七.多表查询

多表查询,也称为关联查询,指两个或更多个表一起完成查询操作。

前提条件:这些一起查询的表之间是有关系的(一对一、一对多),它们之间一定是有关联字段,这个关联字段可能建立了外键,也可能没有建立外键。比如:员工表和部门表,这两个表依靠“部门编号”进行关联。

笛卡尔积的错误:

  • 省略多个表的连接条件(或关联条件)

  • 连接条件(或关联条件)无效

  • 所有表中的所有行互相连接

SELECT	table1.column, table2.column
FROM	table1, table2
WHERE	table1.column1 = table2.column2;  #连接条件

建议:每个字段前,都指明其所在的表

           可以给表起别名

7.1多表查询的分类

7.1.1等值连接 vs 非等值连接

等值连接

SELECT employees.employee_id, employees.last_name, 
       employees.department_id, departments.department_id,
       departments.location_id
FROM   employees, departments
WHERE  employees.department_id = departments.department_id;

非等值连接

SELECT e.last_name, e.salary, j.grade_level
FROM   employees e, job_grades j
WHERE  e.salary BETWEEN j.lowest_sal AND j.highest_sal;

7.1.2自连接和非自连接

自连接

SELECT CONCAT(worker.last_name ,' works for ' 
       , manager.last_name)
FROM   employees worker, employees manager
WHERE  worker.manager_id = manager.employee_id ;

7.1.3内连接和外连接   

  • 内连接: 合并具有同一列的两个以上的表的行, 结果集中不包含一个表与另一个表不匹配的行

  • 外连接: 两个表在连接过程中除了返回满足连接条件的行以外还返回左(或右)表中不满足条件的行 ,这种连接称为左(或右) 外连接。没有匹配的行时, 结果表中相应的列为空(NULL)。

  • 如果是左外连接,则连接条件中左边的表也称为主表,右边的表称为从表

    如果是右外连接,则连接条件中右边的表也称为主表,左边的表称为从表

  • 外连接的分类:左外连接,右外连接,满外连接

SQL92

          左外连接:

SELECT last_name,department_name
FROM employees ,departments
WHERE employees.department_id = departments.department_id(+);

           右外连接:

SELECT last_name,department_name
FROM employees ,departments
WHERE employees.department_id(+) = departments.department_id;

MYSQL不支持SQL92

SQL99

实现内连接:

使用JOIN...ON子句创建连接的语法结构:

SELECT e.employee_id, e.last_name, e.department_id, 
       d.department_id, d.location_id
FROM   employees e JOIN departments d
ON     (e.department_id = d.department_id);

实现外连接:

SELECT e.last_name, e.department_id, d.department_name
FROM   employees e
LEFT OUTER JOIN departments d
ON   (e.department_id = d.department_id) ;

实现满外连接:

  • 满外连接的结果 = 左右表匹配的数据 + 左表没有匹配到的数据 + 右表没有匹配到的数据。

  • SQL99是支持满外连接的。使用FULL JOIN 或 FULL OUTER JOIN来实现。

  • 需要注意的是,MySQL不支持FULL JOIN,但是可以用 LEFT JOIN UNION RIGHT join代替。

7.2UNION关键字

尽量用UNOIN  ALL:不会执行去重操作

UNION ALL操作符返回两个查询的结果集的并集。对于两个结果集的重复部分,不去重。

7.3七种JOIN的实现

 代码实现:

 【强制】超过三个表禁止 join。需要 join 的字段,数据类型保持绝对一致;多表关联查询时, 保证被关联的字段需要有索引。

八.单行函数

8.1函数的分类

8.1.1单行函数

  • 操作数据对象

  • 接受参数返回一个结果

  • 只对一行进行变换

  • 每行返回一个结果

  • 可以嵌套

  • 参数可以是一列或一个值

8.1.2多行函数

8.2数值函数

函数用法
ABS(x)返回x的绝对值
SIGN(X)返回X的符号。正数返回1,负数返回-1,0返回0
PI()返回圆周率的值
CEIL(x),CEILING(x)返回大于或等于某个值的最小整数
FLOOR(x)返回小于或等于某个值的最大整数
LEAST(e1,e2,e3…)返回列表中的最小值
GREATEST(e1,e2,e3…)返回列表中的最大值
MOD(x,y)返回X除以Y后的余数
RAND()返回0~1的随机值
RAND(x)返回0~1的随机值,其中x的值用作种子值,相同的X值会产生相同的随机数
ROUND(x)返回一个对x的值进行四舍五入后,最接近于X的整数
ROUND(x,y)返回一个对x的值进行四舍五入后最接近X的值,并保留到小数点后面Y位
TRUNCATE(x,y)返回数字x截断为y位小数的结果
SQRT(x)返回x的平方根。当X的值为负数时,返回NULL

8.3角度与弧度互换函数

函数用法
RADIANS(x)将角度转化为弧度,其中,参数x为角度值
DEGREES(x)将弧度转化为角度,其中,参数x为弧度值

8.4三角函数

函数用法
SIN(x)返回x的正弦值,其中,参数x为弧度值
ASIN(x)返回x的反正弦值,即获取正弦为x的值。如果x的值不在-1到1之间,则返回NULL
COS(x)返回x的余弦值,其中,参数x为弧度值
ACOS(x)返回x的反余弦值,即获取余弦为x的值。如果x的值不在-1到1之间,则返回NULL
TAN(x)返回x的正切值,其中,参数x为弧度值
ATAN(x)返回x的反正切值,即返回正切值为x的值
ATAN2(m,n)返回两个参数的反正切值
COT(x)返回x的余切值,其中,X为弧度值

8.5指数和对数

函数用法
POW(x,y),POWER(X,Y)返回x的y次方
EXP(X)返回e的X次方,其中e是一个常数,2.718281828459045
LN(X),LOG(X)返回以e为底的X的对数,当X <= 0 时,返回的结果为NULL
LOG10(X)返回以10为底的X的对数,当X <= 0 时,返回的结果为NULL
LOG2(X)返回以2为底的X的对数,当X <= 0 时,返回NULL

8.6进制间的转换

函数用法
BIN(x)返回x的二进制编码
HEX(x)返回x的十六进制编码
OCT(x)返回x的八进制编码
CONV(x,f1,f2)返回f1进制数变成f2进制数

8.7字符串函数

函数用法
ASCII(S)返回字符串S中的第一个字符的ASCII码值
CHAR_LENGTH(s)返回字符串s的字符数。作用与CHARACTER_LENGTH(s)相同
LENGTH(s)返回字符串s的字节数,和字符集有关
CONCAT(s1,s2,......,sn)连接s1,s2,......,sn为一个字符串
CONCAT_WS(x, s1,s2,......,sn)同CONCAT(s1,s2,...)函数,但是每个字符串之间要加上x
INSERT(str, idx, len, replacestr)将字符串str从第idx位置开始,len个字符长的子串替换为字符串replacestr
REPLACE(str, a, b)用字符串b替换字符串str中所有出现的字符串a
UPPER(s) 或 UCASE(s)将字符串s的所有字母转成大写字母
LOWER(s) 或LCASE(s)将字符串s的所有字母转成小写字母
LEFT(str,n)返回字符串str最左边的n个字符
RIGHT(str,n)返回字符串str最右边的n个字符
LPAD(str, len, pad)用字符串pad对str最左边进行填充,直到str的长度为len个字符
RPAD(str ,len, pad)用字符串pad对str最右边进行填充,直到str的长度为len个字符
LTRIM(s)去掉字符串s左侧的空格
RTRIM(s)去掉字符串s右侧的空格
TRIM(s)去掉字符串s开始与结尾的空格
TRIM(s1 FROM s)去掉字符串s开始与结尾的s1
TRIM(LEADING s1 FROM s)去掉字符串s开始处的s1
TRIM(TRAILING s1 FROM s)去掉字符串s结尾处的s1
REPEAT(str, n)返回str重复n次的结果
SPACE(n)返回n个空格
STRCMP(s1,s2)比较字符串s1,s2的ASCII码值的大小
SUBSTR(s,index,len)返回从字符串s的index位置其len个字符,作用与SUBSTRING(s,n,len)、MID(s,n,len)相同
LOCATE(substr,str)返回字符串substr在字符串str中首次出现的位置,作用于POSITION(substr IN str)、INSTR(str,substr)相同。未找到,返回0
ELT(m,s1,s2,…,sn)返回指定位置的字符串,如果m=1,则返回s1,如果m=2,则返回s2,如果m=n,则返回sn
FIELD(s,s1,s2,…,sn)返回字符串s在字符串列表中第一次出现的位置
FIND_IN_SET(s1,s2)返回字符串s1在字符串s2中出现的位置。其中,字符串s2是一个以逗号分隔的字符串
REVERSE(s)返回s反转后的字符串
NULLIF(value1,value2)比较两个字符串,如果value1与value2相等,则返回NULL,否则返回value1

 8.8日期和时间函数

8.1.1 获取日期、时间

函数用法
CURDATE() ,CURRENT_DATE()返回当前日期,只包含年、月、日
CURTIME() , CURRENT_TIME()返回当前时间,只包含时、分、秒
NOW() / SYSDATE() / CURRENT_TIMESTAMP() / LOCALTIME() / LOCALTIMESTAMP()返回当前系统日期和时间
UTC_DATE()返回UTC(世界标准时间)日期
UTC_TIME()返回UTC(世界标准时间)时间

8.2.2 日期与时间戳的转换

函数用法
UNIX_TIMESTAMP()以UNIX时间戳的形式返回当前时间。SELECT UNIX_TIMESTAMP() ->1634348884
UNIX_TIMESTAMP(date)将时间date以UNIX时间戳的形式返回。
FROM_UNIXTIME(timestamp)将UNIX时间戳的时间转换为普通格式的时间

8.8.3 获取月份、星期、星期数、天数等函数

函数用法
YEAR(date) / MONTH(date) / DAY(date)返回具体的日期值
HOUR(time) / MINUTE(time) / SECOND(time)返回具体的时间值
MONTHNAME(date)返回月份:January,...
DAYNAME(date)返回星期几:MONDAY,TUESDAY.....SUNDAY
WEEKDAY(date)返回周几,注意,周1是0,周2是1,。。。周日是6
QUARTER(date)返回日期对应的季度,范围为1~4
WEEK(date) , WEEKOFYEAR(date)返回一年中的第几周
DAYOFYEAR(date)返回日期是一年中的第几天
DAYOFMONTH(date)返回日期位于所在月份的第几天
DAYOFWEEK(date)返回周几,注意:周日是1,周一是2,。。。周六是7

8.8.4 日期的操作函数

函数用法
EXTRACT(type FROM date)返回指定日期中特定的部分,type指定返回的值

8.8.5 时间和秒钟转换的函数

函数用法
TIME_TO_SEC(time)将 time 转化为秒并返回结果值。转化的公式为:小时*3600+分钟*60+秒
SEC_TO_TIME(seconds)将 seconds 描述转化为包含小时、分钟和秒的时间

8.8.6 计算日期和时间的函数

函数用法
DATE_ADD(datetime, INTERVAL expr type),ADDDATE(date,INTERVAL expr type)返回与给定日期时间相差INTERVAL时间段的日期时间
DATE_SUB(date,INTERVAL expr type),SUBDATE(date,INTERVAL expr type)返回与date相差INTERVAL时间间隔的日期
函数用法
ADDTIME(time1,time2)返回time1加上time2的时间。当time2为一个数字时,代表的是,可以为负数
SUBTIME(time1,time2)返回time1减去time2后的时间。当time2为一个数字时,代表的是,可以为负数
DATEDIFF(date1,date2)返回date1 - date2的日期间隔天数
TIMEDIFF(time1, time2)返回time1 - time2的时间间隔
FROM_DAYS(N)返回从0000年1月1日起,N天以后的日期
TO_DAYS(date)返回日期date距离0000年1月1日的天数
LAST_DAY(date)返回date所在月份的最后一天的日期
MAKEDATE(year,n)针对给定年份与所在年份中的天数返回一个日期
MAKETIME(hour,minute,second)将给定的小时、分钟和秒组合成时间并返回
PERIOD_ADD(time,n)返回time加上n后的时间

8.8.7 日期的格式化与解析

函数用法
DATE_FORMAT(date,fmt)按照字符串fmt格式化日期date值
TIME_FORMAT(time,fmt)按照字符串fmt格式化时间time值
GET_FORMAT(date_type,format_type)返回日期字符串的显示格式
STR_TO_DATE(str, fmt)按照字符串fmt对str进行解析,解析为一个日期

上述非GET_FORMAT函数中fmt参数常用的格式符:

格式符说明格式符说明
%Y4位数字表示年份%y表示两位数字表示年份
%M月名表示月份(January,....)%m两位数字表示月份(01,02,03。。。)
%b缩写的月名(Jan.,Feb.,....)%c数字表示月份(1,2,3,...)
%D英文后缀表示月中的天数(1st,2nd,3rd,...)%d两位数字表示月中的天数(01,02...)
%e数字形式表示月中的天数(1,2,3,4,5.....)
%H两位数字表示小数,24小时制(01,02..)%h和%I两位数字表示小时,12小时制(01,02..)
%k数字形式的小时,24小时制(1,2,3)%l数字形式表示小时,12小时制(1,2,3,4....)
%i两位数字表示分钟(00,01,02)%S和%s两位数字表示秒(00,01,02...)
%W一周中的星期名称(Sunday...)%a一周中的星期缩写(Sun.,Mon.,Tues.,..)
%w以数字表示周中的天数(0=Sunday,1=Monday....)
%j以3位数字表示年中的天数(001,002...)%U以数字表示年中的第几周,(1,2,3。。)其中Sunday为周中第一天
%u以数字表示年中的第几周,(1,2,3。。)其中Monday为周中第一天
%T24小时制%r12小时制
%pAM或PM%%表示%

8.9流程控制函数

流程处理函数可以根据不同的条件,执行不同的处理流程,可以在SQL语句中实现不同的条件选择。MySQL中的流程处理函数主要包括IF()、IFNULL()和CASE()函数。

函数用法
IF(value,value1,value2)如果value的值为TRUE,返回value1,否则返回value2
IFNULL(value1, value2)如果value1不为NULL,返回value1,否则返回value2
CASE WHEN 条件1 THEN 结果1 WHEN 条件2 THEN 结果2 .... [ELSE resultn] END相当于Java的if...else if...else...
CASE expr WHEN 常量值1 THEN 值1 WHEN 常量值1 THEN 值1 .... [ELSE 值n] END相当于Java的switch...case...

8.10加密与解密函数

加密与解密函数主要用于对数据库中的数据进行加密和解密处理,以防止数据被他人窃取。这些函数在保证数据库安全时非常有用。

函数用法
PASSWORD(str)返回字符串str的加密版本,41位长的字符串。加密结果不可逆,常用于用户的密码加密
MD5(str)返回字符串str的md5加密后的值,也是一种加密方式。若参数为NULL,则会返回NULL
SHA(str)从原明文密码str计算并返回加密后的密码字符串,当参数为NULL时,返回NULL。SHA加密算法比MD5更加安全
ENCODE(value,password_seed)返回使用password_seed作为加密密码加密value
DECODE(value,password_seed)返回使用password_seed作为加密密码解密value

8.11MySQL信息函数

MySQL中内置了一些可以查询MySQL信息的函数,这些函数主要用于帮助数据库开发或运维人员更好地对数据库进行维护工作。

函数用法
VERSION()返回当前MySQL的版本号
CONNECTION_ID()返回当前MySQL服务器的连接数
DATABASE(),SCHEMA()返回MySQL命令行当前所在的数据库
USER(),CURRENT_USER()、SYSTEM_USER(),SESSION_USER()返回当前连接MySQL的用户名,返回结果格式为“主机名@用户名”
CHARSET(value)返回字符串value自变量的字符集
COLLATION(value)返回字符串value的比较规则

8.12其他函数

函数用法
VERSION()返回当前MySQL的版本号
CONNECTION_ID()返回当前MySQL服务器的连接数
DATABASE(),SCHEMA()返回MySQL命令行当前所在的数据库
USER(),CURRENT_USER()、SYSTEM_USER(),SESSION_USER()返回当前连接MySQL的用户名,返回结果格式为“主机名@用户名”
CHARSET(value)返回字符串value自变量的字符集
COLLATION(value)返回字符串value的比较规则

九.聚合函数

9.1聚合函数类型

  • AVG()      只适用于数值类型的字段

  • SUM()     只适用于数值类型的字段

  • MAX()

  • MIN()

  • COUNT()

count(*)会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行。

9.2. GROUP BY

SELECT   department_id, AVG(salary)
FROM     employees
GROUP BY department_id ;
SELECT   department_id dept_id, job_id, SUM(salary)
FROM     employees
GROUP BY department_id, job_id ;

1.SELECT中出现的非组函数的字段必须声明在GROUP BY中,反之,GROUP BY中声明的字段可以不出现在SELECT中

2.GROUP BY 生命在FROM,WHERE后面,声明在ORDER BY,LIMIT前面

3.MySQL中GROUP BY中使用WITH ROLLUP

9.3. HAVING(作用:用来过滤数据的)

如果过滤条件中使用了聚合函数,则必须使用HAVING来替换WHERE

HAVING声明在GROUP BY后面

  1. 行已经被分组。

  2. 使用了聚合函数。

  3. 满足HAVING 子句中条件的分组将被显示。

  4. HAVING 不能单独使用,必须要跟 GROUP BY 一起使用。

WHERE 与 HAVING的区别

优点缺点
WHERE先筛选数据再关联,执行效率高不能使用分组中的计算函数进行筛选
HAVING可以使用分组中的计算函数在最后的结果集中进行筛选,执行效率较低

十.子查询

SQL 中子查询的使用大大增强了 SELECT 查询的能力,因为很多时候查询需要从结果集中获取数据,或者需要从同一个表中先计算得出一个数据结果,然后与这个数据结果(可能是某个标量,也可能是某个集合)进行比较。

#方式三:子查询
SELECT last_name,salary
FROM employees
WHERE salary > (
		SELECT salary
		FROM employees
		WHERE last_name = 'Abel'
		);

10.1 子查询的基本使用

 子查询的分类

分类一:

分类二:

相关子查询和不相关子查询

  • 子查询(内查询)在主查询之前一次执行完成。

  • 子查询的结果被主查询(外查询)使用 。

  • 注意事项

    • 子查询要包含在括号内

    • 将子查询放在比较条件的右侧

    • 单行操作符对应单行子查询,多行操作符对应多行子查询

10.2单行子查询

操作符含义
=equal to
>greater than
>=greater than or equal to
<less than
<=less than or equal to
<>not equal to
SELECT last_name, job_id, salary
FROM   employees
WHERE  job_id =  
                (SELECT job_id
                 FROM   employees
                 WHERE  employee_id = 141)
AND    salary >
                (SELECT salary
                 FROM   employees
                 WHERE  employee_id = 143);

10.2.1HAVING中的子查询

SELECT   department_id, MIN(salary)
FROM     employees
GROUP BY department_id
HAVING   MIN(salary) >
                       (SELECT MIN(salary)
                        FROM   employees
                        WHERE  department_id = 50);

10.2.2CASE中的子查询

SELECT employee_id, last_name,
       (CASE department_id
        WHEN
             (SELECT department_id FROM departments
	      WHERE location_id = 1800)           
        THEN 'Canada' ELSE 'USA' END) location
FROM   employees;

10.2.3非法使用子查询(子查询查出来多行数据)

SELECT employee_id, last_name
FROM   employees
WHERE  salary =
                (SELECT   MIN(salary)
                 FROM     employees
                 GROUP BY department_id);

10.3多行子查询

操作符含义
IN等于列表中的任意一个
ANY需要和单行比较操作符一起使用,和子查询返回的某一个值比较
ALL需要和单行比较操作符一起使用,和子查询返回的所有值比较
SOME实际上是ANY的别名,作用相同,一般常使用ANY

MySQL中聚合函数不能嵌套使用

10.4相关子查询

如果子查询的执行依赖于外部查询,通常情况下都是因为子查询中的表用到了外部的表,并进行了条件关联,因此每执行一次外部查询,子查询都要重新计算一次,这样的子查询就称之为关联子查询

SELECT last_name,salary,e1.department_id
FROM employees e1,(SELECT department_id,AVG(salary) dept_avg_sal FROM employees GROUP BY department_id) e2
WHERE e1.`department_id` = e2.department_id
AND e2.dept_avg_sal < e1.`salary`;

除了GROUP BY 和LIMIT之外,其他地方都可以声明子查询

10.4.1EXISTS 与 NOT EXISTS关键字

  • 关联子查询通常也会和 EXISTS操作符一起来使用,用来检查在子查询中是否存在满足条件的行。

  • 如果在子查询中不存在满足条件的行:

    • 条件返回 FALSE

    • 继续在子查询中查找

  • 如果在子查询中存在满足条件的行:

    • 不在子查询中继续查找

    • 条件返回 TRUE

  • NOT EXISTS关键字表示如果不存在某种条件,则返回TRUE,否则返回FALSE。十.

十.创建和管理表

10.1标识符命名规则

  • 数据库名、表名不得超过30个字符,变量名限制为29个

  • 必须只能包含 A–Z, a–z, 0–9, _共63个字符

  • 数据库名、表名、字段名等对象名中间不要包含空格

  • 同一个MySQL软件中,数据库不能同名;同一个库中,表不能重名;同一个表中,字段不能重名

  • 必须保证你的字段没有和保留字、数据库系统或常用方法冲突。如果坚持使用,请在SQL语句中使用`(着重号)引起来

  • 保持字段名和类型的一致性:在命名字段并为其指定数据类型的时候一定要保证一致性,假如数据类型在一个表里是整数,那在另一个表里可就别变成字符型了

10.2创建和管理数据库

10.2.1如何创建数据库

  • 方式1:创建数据库

CREATE DATABASE 数据库名; 
  • 方式2:创建数据库并指定字符集

CREATE DATABASE 数据库名 CHARACTER SET 字符集;
  • 方式3:判断数据库是否已经存在,不存在则创建数据库(推荐

CREATE DATABASE IF NOT EXISTS 数据库名; 

注意:DATABASE 不能改名。一些可视化工具可以改名,它是建新库,把所有表复制到新库,再删旧库完成的。

10.2.2使用数据库

  • 查看当前所有的数据库

SHOW DATABASES; #有一个S,代表多个数据库
  • 查看当前正在使用的数据库

SELECT DATABASE();  #使用的一个 mysql 中的全局函数
  • 查看指定库下所有的表

SHOW TABLES FROM 数据库名;
  • 查看数据库的创建信息

SHOW CREATE DATABASE 数据库名;
或者:
SHOW CREATE DATABASE 数据库名\G
  • 使用/切换数据库

USE 数据库名;

注意:要操作表格和数据之前必须先说明是对哪个数据库进行操作,否则就要对所有对象加上“数据库名.”。

10.2.3修改数据库

  • 更改数据库字符集

ALTER DATABASE 数据库名 CHARACTER SET 字符集;  #比如:gbk、utf8等

10.2.4 删除数据库

  • 方式1:删除指定的数据库

DROP DATABASE 数据库名;
  • 方式2:删除指定的数据库(推荐

DROP DATABASE IF EXISTS 数据库名;

数据类新

类型类型举例
整数类型TINYINT、SMALLINT、MEDIUMINT、INT(或INTEGER)、BIGINT
浮点类型FLOAT、DOUBLE
定点数类型DECIMAL
位类型BIT
日期时间类型YEAR、TIME、DATE、DATETIME、TIMESTAMP
文本字符串类型CHAR、VARCHAR、TINYTEXT、TEXT、MEDIUMTEXT、LONGTEXT
枚举类型ENUM
集合类型SET
二进制字符串类型BINARY、VARBINARY、TINYBLOB、BLOB、MEDIUMBLOB、LONGBLOB
JSON类型JSON对象、JSON数组
空间数据类型单值:GEOMETRY、POINT、LINESTRING、POLYGON; 集合:MULTIPOINT、MULTILINESTRING、MULTIPOLYGON、GEOMETRYCOLLECTION

常见数据类型

数据类型描述
INT从-2^31到2^31-1的整型数据。存储大小为 4个字节
CHAR(size)定长字符数据。若未指定,默认为1个字符,最大长度255
VARCHAR(size)可变长字符数据,根据字符串实际长度保存,必须指定长度
FLOAT(M,D)单精度,占用4个字节,M=整数位+小数位,D=小数位。 D<=M<=255,0<=D<=30,默认M+D<=6
DOUBLE(M,D)双精度,占用8个字节,D<=M<=255,0<=D<=30,默认M+D<=15
DECIMAL(M,D)高精度小数,占用M+2个字节,D<=M<=65,0<=D<=30,最大取值范围与DOUBLE相同。
DATE日期型数据,格式'YYYY-MM-DD'
BLOB二进制形式的长文本数据,最大可达4G
TEXT长文本数据,最大可达4G

10.3. 创建表

10.3.1 创建方式

  • 必须具备:

    • CREATE TABLE权限

    • 存储空间

  • 语法格式:方式一:

    CREATE TABLE [IF NOT EXISTS] 表名(
    字段1, 数据类型 [约束条件] [默认值],
    字段2, 数据类型 [约束条件] [默认值],
    字段3, 数据类型 [约束条件] [默认值],
    ……
    [表约束条件]
);

方式二:

CREATE TABLE dept80
AS 
SELECT  employee_id, last_name, salary*12 ANNSAL, hire_date
FROM    employees
WHERE   department_id = 80;

10.3.2查看数据表结构

SHOW CREATE TABLE 表名\G

10.4修改表

使用 ALTER TABLE 语句可以实现:

  • 向已有的表中添加列

  • 修改现有表中的列

  • 删除现有表中的列

  • 重命名现有表中的列

10.4.1追加一个列

ALTER TABLE 表名 ADD 【COLUMN】 字段名 字段类型 【FIRST|AFTER 字段名】;

10.4.2修改一个列

  • 可以修改列的数据类型,长度、默认值和位置

  • 修改字段数据类型、长度、默认值、位置的语法格式如下:

ALTER TABLE 表名 MODIFY 【COLUMN】 字段名1 字段类型 【DEFAULT 默认值】【FIRST|AFTER 字段名2】;

10.4.3重命名一个列

使用 CHANGE old_column new_column dataType子句重命名列。语法格式如下:

ALTER TABLE 表名 CHANGE 【column】 列名 新列名 新数据类型;

10.4.4删除一个列

删除表中某个字段的语法格式如下:

ALTER TABLE 表名 DROP 【COLUMN】字段名

10.5重命名表

RENAME TABLE emp
TO myemp;

10.6删除表

  • 在MySQL中,当一张数据表没有与其他任何数据表形成关联关系时,可以将当前数据表直接删除。

  • 数据和结构都被删除

  • 所有正在运行的相关事务被提交

  • 所有相关索引被删除

  • 语法格式:

DROP TABLE [IF EXISTS] 数据表1 [, 数据表2, …, 数据表n];
  • DROP TABLE 语句不能回滚

10.7清空表

清空表中所有数据,但是表结构保留

TRUNCATE TABLE detail_dept;
  • TRUNCATE语句不能回滚,而使用 DELETE 语句删除数据,可以回滚

十一.数据处理之增删改

11.1插入数据

情况1:为表的所有字段按默认顺序插入数据

INSERT INTO 表名
VALUES (value1,value2,....);

一定按照字段生命顺序添加

情况2:为表的指定字段插入数据

INSERT INTO 表名(column1 [, column2, …, columnn]) 
VALUES (value1 [,value2, …, valuen]);

例子

INSERT INTO departments(department_id, department_name)
VALUES (80, 'IT');

情况3:同时插入多条记录

INSERT INTO table_name 
VALUES 
(value1 [,value2, …, valuen]),
(value1 [,value2, …, valuen]),
……
(value1 [,value2, …, valuen]);
INSERT INTO table_name(column1 [, column2, …, columnn]) 
VALUES 
(value1 [,value2, …, valuen]),
(value1 [,value2, …, valuen]),
……
(value1 [,value2, …, valuen]);

情况4:将查询结果插入到表中

INSERT INTO 目标表名
(tar_column1 [, tar_column2, …, tar_columnn])
SELECT
(src_column1 [, src_column2, …, src_columnn])
FROM 源表名
[WHERE condition]
  • 在 INSERT 语句中加入子查询。

  • 不必书写 VALUES 子句。

  • 子查询中的值列表应与 INSERT 子句中的列名对应。

  • 举例:
INSERT INTO sales_reps(id, name, salary, commission_pct)
SELECT employee_id, last_name, salary, commission_pct
FROM   employees
WHERE  job_id LIKE '%REP%';

11.2更新数据

  • 使用 UPDATE 语句更新数据。语法如下:

UPDATE table_name
SET column1=value1, column2=value2, … , column=valuen
[WHERE condition]
  • 可以一次更新多条数据。

  • 如果需要回滚数据,需要保证在DML前,进行设置:SET AUTOCOMMIT = FALSE;


  • 使用 WHERE 子句指定需要更新的数据。

UPDATE employees
SET    department_id = 70
WHERE  employee_id = 113;

11.3删除数据

  • 使用 DELETE 语句从表中删除数据

DELETE FROM table_name [WHERE <condition>];
  • 使用 WHERE 子句删除指定的记录。

DELETE FROM departments
WHERE  department_name = 'Finance';

小结:DML操作默认情况下执行完以后,都会自动提交数据

           如果希望执行完之后不自动提交,则需要使用SET autocommit=FALSE

11.4MySQL8新特性:计算列

CREATE TABLE tb1(
id INT,
a INT,
b INT,
c INT GENERATED ALWAYS AS (a + b) VIRTUAL
);

十三.MySQL数据类型精讲

13.1. MySQL中的数据类型

类型类型举例
整数类型TINYINT、SMALLINT、MEDIUMINT、INT(或INTEGER)、BIGINT
浮点类型FLOAT、DOUBLE
定点数类型DECIMAL
位类型BIT
日期时间类型YEAR、TIME、DATE、DATETIME、TIMESTAMP
文本字符串类型CHAR、VARCHAR、TINYTEXT、TEXT、MEDIUMTEXT、LONGTEXT
枚举类型ENUM
集合类型SET
二进制字符串类型BINARY、VARBINARY、TINYBLOB、BLOB、MEDIUMBLOB、LONGBLOB
JSON类型JSON对象、JSON数组
空间数据类型单值类型:GEOMETRY、POINT、LINESTRING、POLYGON; 集合类型:MULTIPOINT、MULTILINESTRING、MULTIPOLYGON、GEOMETRYCOLLECTION

常见数据类型的属性,如下:

MySQL关键字含义
NULL数据列可包含NULL值
NOT NULL数据列不允许包含NULL值
DEFAULT默认值
PRIMARY KEY主键
AUTO_INCREMENT自动递增,适用于整数类型
UNSIGNED无符号
CHARACTER SET name指定一个字符集

13.2整数类型

13.2.1 类型介绍

整数类型一共有 5 种,包括 TINYINT、SMALLINT、MEDIUMINT、INT(INTEGER)和 BIGINT。

它们的区别如下表所示:

整数类型字节有符号数取值范围无符号数取值范围
TINYINT1-128~1270~255
SMALLINT2-32768~327670~65535
MEDIUMINT3-8388608~83886070~16777215
INT、INTEGER4-2147483648~21474836470~4294967295
BIGINT8-9223372036854775808~92233720368547758070~18446744073709551615

UNSIGNED: 无符号类型(非负),所有的整数类型都有一个可选的属性UNSIGNED(无符号属性),无符号整数类型的最小取值为0。所以,如果需要在MySQL数据库中保存非负整数值时,可以将整数类型设置为无符号类型。

ZEROFILL: 0填充,(如果某列是ZEROFILL,那么MySQL会自动为当前列添加UNSIGNED属性),如果指定了ZEROFILL只是表示不够M位时,用0在左边填充,如果超过M位,只要不超过数据存储范围即可。

适用场景:

TINYINT:一般用于枚举数据,比如系统设定取值范围很小且固定的场景。

SMALLINT:可以用于较小范围的统计数据,比如统计工厂的固定资产库存数量等。

MEDIUMINT:用于较大整数的计算,比如车站每日的客流量等。

INT、INTEGER:取值范围足够大,一般情况下不用考虑超限问题,用得最多。比如商品编号。

BIGINT:只有当你处理特别巨大的整数时才会用到。比如双十一的交易量、大型门户网站点击量、证券公司衍生产品持仓等。

13.3. 浮点类型

  • FLOAT 表示单精度浮点数;

  • DOUBLE 表示双精度浮点数;

问题1:FLOAT 和 DOUBLE 这两种数据类型的区别是啥呢?

FLOAT 占用字节数少,取值范围小;DOUBLE 占用字节数多,取值范围也大。

13.4定点数类型(建议使用)

  • MySQL中的定点数类型只有 DECIMAL 一种类型。
数据类型字节数含义
DECIMAL(M,D),DEC,NUMERICM+2字节有效范围由M和D决定
  • 浮点数 vs 定点数

    • 浮点数相对于定点数的优点是在长度一定的情况下,浮点类型取值范围大,但是不精准,适用于需要取值范围大,又可以容忍微小误差的科学计算场景(比如计算化学、分子建模、流体动力学等)

    • 定点数类型取值范围相对小,但是精准,没有误差,适合于对精度要求极高的场景 (比如涉及金额计算的场景)

13.5. 日期与时间类型

MySQL有多种表示日期和时间的数据类型,不同的版本可能有所差异,MySQL8.0版本支持的日期和时间类型主要有:YEAR类型、TIME类型、DATE类型、DATETIME类型和TIMESTAMP类型。

  • YEAR类型通常用来表示年

  • DATE类型通常用来表示年、月、日

  • TIME类型通常用来表示时、分、秒

  • DATETIME类型通常用来表示年、月、日、时、分、秒

  • TIMESTAMP类型通常用来表示带时区的年、月、日、时、分、秒

类型名称字节日期格式最小值最大值
YEAR1YYYY或YY19012155
TIME时间3HH:MM:SS-838:59:59838:59:59
DATE日期3YYYY-MM-DD1000-01-019999-12-03
DATETIME日期时间8YYYY-MM-DD HH:MM:SS1000-01-01 00:00:009999-12-31 23:59:59
TIMESTAMP日期时间4YYYY-MM-DD HH:MM:SS1970-01-01 00:00:00 UTC2038-01-19 03:14:07UTC

13.5.1YEARS类型

  • 以4位字符串或数字格式表示YEAR类型,其格式为YYYY,最小值为1901,最大值为2155。

13.5.2DATE类型

  • YYYY-MM-DD格式或者YYYYMMDD格式表示的字符串日期,其最小取值为1000-01-01,最大取值为9999-12-03。YYYYMMDD格式会被转化为YYYY-MM-DD格式。

  • YY-MM-DD格式或者YYMMDD格式表示的字符串日期,此格式中,年份为两位数值或字符串满足YEAR类型的格式条件为:当年份取值为00到69时,会被转化为2000到2069;当年份取值为70到99时,会被转化为1970到1999。

  • 使用CURRENT_DATE()或者NOW()函数,会插入当前系统的日期。

13.5.3 TIME类型

可以使用带有冒号的字符串,比如'D HH:MM:SS'、'HH:MM:SS'、'HH:MM'、'D HH:MM'、'D HH'或'SS'格式,都能被正确地插入TIME类型的字段中。其中D表示天,其最小值为0,最大值为34。如果使用带有D格式的字符串插入TIME类型的字段时,D会被转化为小时,计算格式为D*24+HH。当使用带有冒号并且不带D的字符串表示时间时,表示当天的时间,比如12:10表示12:10:00,而不是00:12:10。

13.5.4 DATETIME类型

YYYY-MM-DD HH:MM:SS格式或者YYYYMMDDHHMMSS格式的字符串插入DATETIME类型的字段时,最小值为1000-01-01 00:00:00,最大值为9999-12-03 23:59:59。

13.5.5 TIMESTAMP类型

TIMESTAMP类型也可以表示日期时间,其显示格式与DATETIME类型相同,都是YYYY-MM-DD HH:MM:SS,需要4个字节的存储空间。但是TIMESTAMP存储的时间范围比DATETIME要小很多,只能存储“1970-01-01 00:00:01 UTC”到“2038-01-19 03:14:07 UTC”之间的时间。其中,UTC表示世界统一时间,也叫作世界标准时间。

13.6. 文本字符串类型

MySQL中,文本字符串总体上分为CHARVARCHARTINYTEXTTEXTMEDIUMTEXTLONGTEXTENUMSET等类型。

13.6.1 CHAR与VARCHAR类型

字符串(文本)类型特点长度长度范围占用的存储空间
CHAR(M)固定长度M0 <= M <= 255M个字节
VARCHAR(M)可变长度M0 <= M <= 65535(实际长度 + 1) 个字节

CHAR类型:

  • CHAR(M) 类型一般需要预先定义字符串长度。如果不指定(M),则表示长度默认是1个字符。

  • 如果保存时,数据的实际长度比CHAR类型声明的长度小,则会在右侧填充空格以达到指定的长度。当MySQL检索CHAR类型的数据时,CHAR类型的字段会去除尾部的空格。

  • 定义CHAR类型字段时,声明的字段长度即为CHAR类型字段所占的存储空间的字节数。

VARCHAR类型:

  • VARCHAR(M) 定义时,必须指定长度M,否则报错。

  • MySQL4.0版本以下,varchar(20):指的是20字节,如果存放UTF8汉字时,只能存6个(每个汉字3字节) ;MySQL5.0版本以上,varchar(20):指的是20字符。

  • 检索VARCHAR类型的字段数据时,会保留数据尾部的空格。VARCHAR类型的字段所占用的存储空间为字符串实际长度加1个字节。

13.6.2 TEXT类型

文本字符串类型特点长度长度范围占用的存储空间
TINYTEXT小文本、可变长度L0 <= L <= 255L + 2 个字节
TEXT文本、可变长度L0 <= L <= 65535L + 2 个字节
MEDIUMTEXT中等文本、可变长度L0 <= L <= 16777215L + 3 个字节
LONGTEXT大文本、可变长度L0 <= L<= 4294967295(相当于4GB)L + 4 个字节

TEXT文本类型,可以存比较大的文本段,搜索速度稍慢,因此如果不是特别大的内容,建议使用CHAR,VARCHAR来代替。还有TEXT类型不用加默认值,加了也没用。而且text和blob类型的数据删除后容易导致“空洞”,使得文件碎片比较多,所以频繁使用的表不建议包含TEXT类型字段,建议单独分出去,单独用一个表。

13.7. ENUM类型

ENUM类型也叫作枚举类型,ENUM类型的取值范围需要在定义字段时进行指定。设置字段值时,ENUM类型只允许从成员中选取单个值,不能一次选取多个值。

其所需要的存储空间由定义ENUM类型时指定的成员个数决定。

文本字符串类型长度长度范围占用的存储空间
ENUML1 <= L <= 655351或2个字节

13.8. SET类型

SET表示一个字符串对象,可以包含0个或多个成员,但成员个数的上限为64。设置字段值时,可以取取值范围内的 0 个或多个值。

当SET类型包含的成员个数不同时,其所占用的存储空间也是不同的,具体如下:

成员个数范围(L表示实际成员个数)占用的存储空间
1 <= L <= 81个字节
9 <= L <= 162个字节
17 <= L <= 243个字节
25 <= L <= 324个字节
33 <= L <= 648个字节

13.9. 二进制字符串类型

13.9.1BINARY与VARBINARY类型

BINARY和VARBINARY类似于CHAR和VARCHAR,只是它们存储的是二进制字符串。

二进制字符串类型特点值的长度占用空间
BINARY(M)固定长度M (0 <= M <= 255)M个字节
VARBINARY(M)可变长度M(0 <= M <= 65535)M+1个字节

13.9.2BLOB类型

BLOB是一个二进制大对象,可以容纳可变数量的数据。

MySQL中的BLOB类型包括TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB 4种类型,它们可容纳值的最大长度不同。可以存储一个二进制的大对象,比如图片音频视频等。

需要注意的是,在实际工作中,往往不会在MySQL数据库中使用BLOB类型存储大对象数据,通常会将图片、音频和视频文件存储到服务器的磁盘上,并将图片、音频和视频的访问路径存储到MySQL中。

二进制字符串类型值的长度长度范围占用空间
TINYBLOBL0 <= L <= 255L + 1 个字节
BLOBL0 <= L <= 65535(相当于64KB)L + 2 个字节
MEDIUMBLOBL0 <= L <= 16777215 (相当于16MB)L + 3 个字节
LONGBLOBL0 <= L <= 4294967295(相当于4GB)L + 4 个字节

13.10JOSN类型

JSON 可以将 JavaScript 对象中表示的一组数据转换为字符串,然后就可以在网络或者程序之间轻松地传递这个字符串,并在需要的时候将它还原为各编程语言所支持的数据格式。

创建数据表,表中包含一个JSON类型的字段 js 。

CREATE TABLE test_json(
js json

);

向表中插入JSON数据。

INSERT INTO test_json (js) 
VALUES ('{"name":"songhk", "age":18, "address":{"province":"beijing", "city":"beijing"}}');

查询t19表中的数据。

mysql> SELECT *
    -> FROM test_json;

当需要检索JSON类型的字段中数据的某个具体值时,可以使用“->”和“->>”符号。

mysql> SELECT js -> '$.name' AS NAME,js -> '$.age' AS age ,js -> '$.address.province' AS province, js -> '$.address.city' AS city
    -> FROM test_json;

小结:

在定义数据类型时,如果确定是整数,就用INT; 如果是小数,一定用定点数类型 DECIMAL(M,D); 如果是日期与时间,就用 DATETIME

  • 任何字段如果为非负数,必须是 UNSIGNED

十四.约束

数据完整性(Data Integrity)是指数据的精确性(Accuracy)和可靠性(Reliability)。它是防止数据库中存在不符合语义规定的数据和防止因错误信息的输入输出造成无效操作或错误信息而提出的。

14.1约束的分类:

  • 根据约束数据列的限制,约束可分为:

    • 单列约束:每个约束只约束一列

    • 多列约束:每个约束可约束多列数据

  • 根据约束的作用范围,约束可分为:

    • 列级约束:只能作用在一个列上,跟在列的定义后面

    • 表级约束:可以作用在多个列上,不与列一起,而是单独定义

            位置            支持的约束类型                    是否可以起约束名
列级约束:    列的后面        语法都支持,但外键没有效果        不可以
表级约束:    所有列的下面       默认和非空不支持,其他支持       可以(主键没有效果)

  • 根据约束起的作用,约束可分为:

    • NOT NULL 非空约束,规定某个字段不能为空

    • UNIQUE 唯一约束规定某个字段在整个表中是唯一的

    • PRIMARY KEY 主键(非空且唯一)约束

    • FOREIGN KEY 外键约束

    • CHECK 检查约束

    • DEFAULT 默认值约束

如何查看表中的约束:

SELECT * FROM information_schema.table_constraints 
WHERE table_name = '表名称';

14.2非空约束

14.2.1作用

限定某个字段/某列的值不允许为空

14.2.2 关键字

NOT NULL

14.2.3 特点

  • 默认,所有的类型的值都可以是NULL,包括INT、FLOAT等数据类型

  • 非空约束只能出现在表对象的列上,只能某个列单独限定非空,不能组合非空

  • 一个表可以有很多列都分别限定了非空

  • 空字符串''不等于NULL,0也不等于NULL

14.2.4 添加非空约束

(1)建表时

CREATE TABLE 表名称(
	字段名  数据类型,
    字段名  数据类型 NOT NULL,  
    字段名  数据类型 NOT NULL
);

(2)建表后

alter table 表名称 modify 字段名 数据类型 not null;

14.2.5 删除非空约束

alter table 表名称 modify 字段名 数据类型 NULL;#去掉not null,相当于修改某个非注解字段,该字段允许为空

或 

alter table 表名称 modify 字段名 数据类型;#去掉not null,相当于修改某个非注解字段,该字段允许为空

14.3. 唯一性约束

14.3.1 作用

用来限制某个字段/某列的值不能重复。

14.3.2 关键字

UNIQUE

14.3.3 特点

  • 同一个表可以有多个唯一约束。

  • 唯一约束可以是某一个列的值唯一,也可以多个列组合的值唯一。

  • 唯一性约束允许列值为空。

  • 在创建唯一约束的时候,如果不给唯一约束命名,就默认和列名相同。

  • MySQL会给唯一约束的列上默认创建一个唯一索引。

14.3.4 添加唯一约束

(1)建表时

create table 表名称(
	字段名  数据类型,
    字段名  数据类型  unique,  
    字段名  数据类型  unique key,
    字段名  数据类型
);
create table 表名称(
	字段名  数据类型,
    字段名  数据类型,  
    字段名  数据类型,
    [constraint 约束名] unique key(字段名)
);

(2)建表后指定唯一键约束

#字段列表中如果是一个字段,表示该列的值唯一。如果是两个或更多个字段,那么复合唯一,即多个字段的组合是唯一的1

#方式1:
alter table 表名称 add unique key(字段列表); 
#方式2:
alter table 表名称 modify 字段名 字段类型 unique;

14.3.5 关于复合唯一约束

create table 表名称(
	字段名  数据类型,
    字段名  数据类型,  
    字段名  数据类型,
    unique key(字段列表) #字段列表中写的是多个字段名,多个字段名用逗号分隔,表示那么是复合唯一,即多个字段的组合是唯一的
);

14.3.6 删除唯一约束

  • 添加唯一性约束的列上也会自动创建唯一索引。

  • 删除唯一约束只能通过删除唯一索引的方式删除。

  • 删除时需要指定唯一索引名,唯一索引名就和唯一约束名一样。

  • 如果创建唯一约束时未指定名称,如果是单列,就默认和列名相同;如果是组合列,那么默认和()中排在第一个的列名相同。也可以自定义唯一性约束名。

SELECT * FROM information_schema.table_constraints WHERE table_name = '表名'; 
#查看都有哪些约束
ALTER TABLE USER 
DROP INDEX uk_name_pwd;

注意:可以通过 show index from 表名称;查看表的索引

14.4. PRIMARY KEY 约束

14.4.1 作用

用来唯一标识表中的一行记录。

14.4.2 关键字

primary key

14.4.3 特点

  • 主键约束相当于唯一约束+非空约束的组合,主键约束列不允许重复,也不允许出现空值。

14.4.4 添加主键约束

(1)建表时指定主键约束

create table 表名称(
	字段名  数据类型  primary key, #列级模式
    字段名  数据类型,  
    字段名  数据类型  
);
create table 表名称(
	字段名  数据类型,
    字段名  数据类型,  
    字段名  数据类型,
    [constraint 约束名] primary key(字段名) #表级模式
);

(2)建表后增加主键约束

ALTER TABLE 表名称 ADD PRIMARY KEY(字段列表); 
#字段列表可以是一个字段,也可以是多个字段,如果是多个字段的话,是复合主键

14.4.5 删除主键约束

alter table 表名称 drop primary key;

14.5. 自增列:AUTO_INCREMENT

14.5.1 作用

某个字段的值自增

14.5.2 关键字

auto_increment

14.5.3 特点和要求

(1)一个表最多只能有一个自增长列

(2)当需要产生唯一标识符或顺序值时,可设置自增长

(3)自增长列约束的列必须是键列(主键列,唯一键列)

(4)自增约束的列的数据类型必须是整数类型

(5)如果自增列指定了 0 和 null,会在当前最大值的基础上自增;如果自增列手动指定了具体值,直接赋值为具体值。

create table 表名称(
	字段名  数据类型  primary key auto_increment,
    字段名  数据类型  unique key not null,  
    字段名  数据类型  unique key,
    字段名  数据类型  not null default 默认值, 
);
alter table 表名称 modify 字段名 数据类型 auto_increment;

删除自增列:

alter table 表名称 modify 字段名 数据类型; 
#去掉auto_increment相当于删除

14.5.4 MySQL 8.0新特性—自增变量的持久化

MySQL 8.0将自增主键的计数器持久化到重做日志中。每次计数器发生改变,都会将其写入重做日志中。如果数据库重启,InnoDB会根据重做日志中的信息来初始化计数器的内存值。

14.6. FOREIGN KEY外键约束

14.6.1 作用

限定某个表的某个字段的引用完整性。

比如:员工表的员工所在部门的选择,必须在部门表能找到对应的部分。

14.6.2 关键字

FOREIGN KEY

14.6.3 主表和从表/父表和子表

主表(父表):被引用的表,被参考的表

从表(子表):引用别人的表,参考别人的表

例如:员工表的员工所在部门这个字段的值要参考部门表:部门表是主表,员工表是从表。

例如:学生表、课程表、选课表:选课表的学生和课程要分别参考学生表和课程表,学生表和课程表是主表,选课表是从表。

14.6.5 添加外键约束

(1)建表时

create table 主表名称(
	字段1  数据类型  primary key,
    字段2  数据类型
);

create table 从表名称(
	字段1  数据类型  primary key,
    字段2  数据类型,
    [CONSTRAINT <外键约束名称>] FOREIGN KEY(从表的某个字段) references 主表名(被参考字段)
);
#(从表的某个字段)的数据类型必须与主表名(被参考字段)的数据类型一致,逻辑意义也一样
#(从表的某个字段)的字段名可以与主表名(被参考字段)的字段名一样,也可以不一样

-- FOREIGN KEY: 在表级指定子表中的列
-- REFERENCES: 标示在父表中的列

关联的主表必须是主键或者唯一性约束的键

(2)建表后

ALTER TABLE 从表名 ADD [CONSTRAINT 约束名] FOREIGN KEY (从表的字段) REFERENCES 主表名(被引用字段) [on update xx][on delete xx];

14.6.7 约束等级

  • Cascade方式:在父表上update/delete记录时,同步update/delete掉子表的匹配记录****

  • Set null方式:在父表上update/delete记录时,将子表上匹配记录的列设为null,但是要注意子表的外键列不能为not null****

  • No action方式:如果子表中有匹配的记录,则不允许对父表对应候选键进行update/delete操作

  • Restrict方式:同no action, 都是立即检查外键约束

  • Set default方式(在可视化工具SQLyog中可能显示空白):父表有变更时,子表将外键列设置成一个默认的值,但Innodb不能识别

如果没有指定等级,就相当于Restrict方式。

对于外键约束,最好是采用: ON UPDATE CASCADE ON DELETE RESTRICT 的方式。

(1)演示1:on update cascade on delete set null

create table dept(
	did int primary key,		#部门编号
    dname varchar(50)			#部门名称
);

create table emp(
	eid int primary key,  #员工编号
    ename varchar(5),     #员工姓名
    deptid int,				#员工所在的部门
    foreign key (deptid) references dept(did)  on update cascade on delete set null
    #把修改操作设置为级联修改等级,把删除操作设置为set null等级
);

(2)演示2:on update set null on delete cascade

create table dept(
	did int primary key,		#部门编号
    dname varchar(50)			#部门名称
);

create table emp(
	eid int primary key,  #员工编号
    ename varchar(5),     #员工姓名
    deptid int,				#员工所在的部门
    foreign key (deptid) references dept(did)  on update set null on delete cascade
    #把修改操作设置为set null等级,把删除操作设置为级联删除等级
);

14.6.8 删除外键约束

(1)第一步先查看约束名和删除外键约束
SELECT * FROM information_schema.table_constraints WHERE table_name = '表名称';#查看某个表的约束名

ALTER TABLE 从表名 DROP FOREIGN KEY 外键约束名;

(2)第二步查看索引名和删除索引。(注意,只能手动删除)
SHOW INDEX FROM 表名称; #查看某个表的索引名

ALTER TABLE 从表名 DROP INDEX 索引名;

14.7. CHECK 约束

14.7.1 作用

检查某个字段的值是否符号xx要求,一般指的是值的范围

14.7.2、关键字

CHECK

14.7.3举例

create table employee(
	eid int primary key,
    ename varchar(5),
    gender char check ('男' or '女')
);

14.8. DEFAULT约束

14.8.1 作用

给某个字段/某列指定默认值,一旦设置默认值,在插入数据时,如果此字段没有显式赋值,则赋值为默认值。

14.8.2 关键字

DEFAULT

14.8.3 如何给字段加默认值

(1)建表时

reate table 表名称(
	字段名  数据类型  primary key,
    字段名  数据类型  unique key not null,  
    字段名  数据类型  unique key,
    字段名  数据类型  not null default 默认值, 
);
create table 表名称(
	字段名  数据类型 default 默认值 ,
    字段名  数据类型 not null default 默认值,  
    字段名  数据类型 not null default 默认值,
    primary key(字段名),
    unique key(字段名)
);

说明:默认值约束一般不在唯一键和主键列上加

(2)建表后

alter table 表名称 modify 字段名 数据类型 default 默认值;

#如果这个字段原来有非空约束,你还保留非空约束,那么在加默认值约束时,还得保留非空约束,否则非空约束就被删除了
#同理,在给某个字段加非空约束也一样,如果这个字段原来有默认值约束,你想保留,也要在modify语句中保留默认值约束,否则就删除了
alter table 表名称 modify 字段名 数据类型 default 默认值 not null;

14.8.4 如何删除默认值约束

alter table 表名称 modify 字段名 数据类型 ;#删除默认值约束,也不保留非空约束

alter table 表名称 modify 字段名 数据类型  not null; #删除默认值约束,保留非空约束

十五.视图

15.1. 常见的数据库对象

对象描述
表(TABLE)表是存储数据的逻辑单元,以行和列的形式存在,列就是字段,行就是记录
数据字典就是系统表,存放数据库相关信息的表。系统表的数据通常由数据库系统维护,程序员通常不应该修改,只可查看
约束(CONSTRAINT)执行数据校验的规则,用于保证数据完整性的规则
视图(VIEW)一个或者多个数据表里的数据的逻辑显示,视图并不存储数据
索引(INDEX)用于提高查询性能,相当于书的目录
存储过程(PROCEDURE)用于完成一次完整的业务处理,没有返回值,但可通过传出参数将多个值传给调用环境
存储函数(FUNCTION)用于完成一次特定的计算,具有一个返回值
触发器(TRIGGER)相当于一个事件监听器,当数据库发生特定事件后,触发器被触发,完成相应的处理
  • 视图是一种虚拟表,本身是不具有数据的,占用很少的内存空间,它是 SQL 中的一个重要概念。

  • 视图建立在已有表的基础上, 视图赖以建立的这些表称为基表

  • 视图的创建和删除只影响视图本身,不影响对应的基表。但是当对视图中的数据进行增加、删除和修改操作时,数据表中的数据会相应地发生变化,反之亦然。

15.2. 创建视图

CREATE VIEW 视图名称 
AS 查询语句

15.2.1 创建单表视图

CREATE VIEW empvu80
AS 
SELECT  employee_id, last_name, salary
FROM    employees
WHERE   department_id = 80;

说明1:实际上就是我们在 SQL 查询语句的基础上封装了视图 VIEW,这样就会基于 SQL 语句的结果集形成一张虚拟表。

说明2:在创建视图时,没有在视图名后面指定字段列表,则视图中字段列表默认和SELECT语句中的字段列表一致。如果SELECT语句中给字段取了别名,那么视图中的字段名和别名相同。

15.2.2 创建多表联合视图

CREATE VIEW emp_dept
AS 
SELECT ename,dname
FROM t_employee LEFT JOIN t_department
ON t_employee.did = t_department.did;

15.2.3 基于视图创建视图

当我们创建好一张视图之后,还可以在它的基础上继续创建视图。

CREATE VIEW emp_dept_ysalary
AS 
SELECT emp_dept.ename,dname,year_salary
FROM emp_dept INNER JOIN emp_year_salary
ON emp_dept.ename = emp_year_salary.ename;

15.2.4. 查看视图

语法1:查看数据库的表对象、视图对象

SHOW TABLES;

语法2:查看视图的结构

DESC / DESCRIBE 视图名称;

语法3:查看视图的属性信息

# 查看视图信息(显示数据表的存储引擎、版本、数据行数和数据大小等)
SHOW TABLE STATUS LIKE '视图名称'\G

不建议更新视图数据

15.3 修改、删除视图

15.3.1 修改视图

方式1:使用CREATE OR REPLACE VIEW 子句修改视图

CREATE OR REPLACE VIEW empvu80
(id_number, name, sal, department_id)
AS 
SELECT  employee_id, first_name || ' ' || last_name, salary, department_id
FROM employees
WHERE department_id = 80;

方式2:ALTER VIEW

ALTER VIEW 视图名称 
AS
查询语句

针对小型项目不建议用视图

十六.存储过程与函数

16.1. 存储过程概述

含义:存储过程的英文是 Stored Procedure。它的思想很简单,就是一组经过预先编译的 SQL 语句的封装。

执行过程:存储过程预先存储在 MySQL 服务器上,需要执行的时候,客户端只需要向服务器端发出调用存储过程的命令,服务器端就可以把预先存储好的这一系列 SQL 语句全部执行。

好处

1、简化操作,提高了sql语句的重用性,减少了开发程序员的压力 2、减少操作过程中的失误,提高效率 3、减少网络传输量(客户端不需要把所有的 SQL 语句通过网络发给服务器) 4、减少了 SQL 语句暴露在网上的风险,也提高了数据查询的安全性

和视图、函数的对比

它和视图有着同样的优点,清晰、安全,还可以减少网络传输量。不过它和视图不同,视图是虚拟表,通常不对底层数据表直接操作,而存储过程是程序化的 SQL,可以直接操作底层数据表,相比于面向集合的操作方式,能够实现一些更复杂的数据处理。

一旦存储过程被创建出来,使用它就像使用函数一样简单,我们直接通过调用存储过程名即可。相较于函数,存储过程是没有返回值的。

 分类

存储过程的参数类型可以是IN、OUT和INOUT。根据这点分类如下:

1、没有参数(无参数无返回) 2、仅仅带 IN 类型(有参数无返回) 3、仅仅带 OUT 类型(无参数有返回) 4、既带 IN 又带 OUT(有参数有返回) 5、带 INOUT(有参数有返回)

注意:IN、OUT、INOUT 都可以在一个存储过程中带多个。

十七.变量、流程控制与游标

17.1. 变量

在MySQL数据库的存储过程和函数中,可以使用变量来存储查询或计算的中间结果数据,或者输出最终的结果数据。

在 MySQL 数据库中,变量分为系统变量以及用户自定义变量

17.1.1 系统变量

系统变量分类

系统变量分为全局系统变量(需要添加global 关键字)以及会话系统变量(需要添加 session 关键字),有时也把全局系统变量简称为全局变量,有时也把会话系统变量称为local变量。如果不写,默认会话级别。静态变量(在 MySQL 服务实例运行期间它们的值不能使用 set 动态修改)属于特殊的全局系统变量。

  • 查看所有或部分系统变量

#查看所有全局变量
SHOW GLOBAL VARIABLES;

#查看所有会话变量
SHOW SESSION VARIABLES;
或
SHOW VARIABLES;
#查看满足条件的部分系统变量。
SHOW GLOBAL VARIABLES LIKE '%标识符%';

#查看满足条件的部分会话变量
SHOW SESSION VARIABLES LIKE '%标识符%';
  • 查看指定系统变量

作为 MySQL 编码规范,MySQL 中的系统变量以两个“@”开头,其中“@@global”仅用于标记全局系统变量,“@@session”仅用于标记会话系统变量。“@@”首先标记会话系统变量,如果会话系统变量不存在,则标记全局系统变量。

#查看指定的系统变量的值
SELECT @@global.变量名;

#查看指定的会话变量的值
SELECT @@session.变量名;
#或者
SELECT @@变量名;
  • 修改系统变量的值

有些时候,数据库管理员需要修改系统变量的默认值,以便修改当前会话或者MySQL服务实例的属性、特征。具体方法:

方式1:修改MySQL配置文件,继而修改MySQL系统变量的值(该方法需要重启MySQL服务)

方式2:在MySQL服务运行期间,使用“set”命令重新设置系统变量的值

#为某个系统变量赋值
#方式1:
SET @@global.变量名=变量值;
#方式2:
SET GLOBAL 变量名=变量值;


#为某个会话变量赋值
#方式1:
SET @@session.变量名=变量值;
#方式2:
SET SESSION 变量名=变量值;

针对当前的数据库实例是有效的,一旦重启mysql服务就失效了

17.1.2 用户变量

17.1.2.1 用户变量分类

用户变量是用户自己定义的,作为 MySQL 编码规范,MySQL 中的用户变量以一个“@”开头。根据作用范围不同,又分为会话用户变量局部变量

  • 会话用户变量:作用域和会话变量一样,只对当前连接会话有效。

  • 局部变量:只在 BEGIN 和 END 语句块中有效。局部变量只能在存储过程和函数中使用。

17.1.2.2 会话用户变量

  • 变量的定义

#方式1:“=”或“:=”
SET @用户变量 = 值;
SET @用户变量 := 值;

#方式2:“:=” 或 INTO关键字
SELECT @用户变量 := 表达式 [FROM 等子句];
SELECT 表达式 INTO @用户变量  [FROM 等子句];

17.1.2.3 局部变量

定义:可以使用DECLARE语句定义一个局部变量

作用域:仅仅在定义它的 BEGIN ... END 中有效

位置:只能放在 BEGIN ... END 中,而且只能放在第一句


BEGIN
	#声明局部变量
	DECLARE 变量名1 变量数据类型 [DEFAULT 变量默认值];
	DECLARE 变量名2,变量名3,... 变量数据类型 [DEFAULT 变量默认值];

	#为局部变量赋值
	SET 变量名1 = 值;
	SELECT 值 INTO 变量名2 [FROM 子句];

	#查看局部变量的值
	SELECT 变量1,变量2,变量3;
END

定义条件:

17.2. 流程控制

17.2.1 分支结构之 IF

  • IF 语句的语法结构是:

IF 表达式1 THEN 操作1
[ELSEIF 表达式2 THEN 操作2]……
[ELSE 操作N]
END IF

17.2.2 分支结构之 CASE

CASE 语句的语法结构1:

#情况一:类似于switch
CASE 表达式
WHEN 值1 THEN 结果1或语句1(如果是语句,需要加分号) 
WHEN 值2 THEN 结果2或语句2(如果是语句,需要加分号)
...
ELSE 结果n或语句n(如果是语句,需要加分号)
END [case](如果是放在begin end中需要加上case,如果放在select后面不需要)

CASE 语句的语法结构2:

#情况二:类似于多重if
CASE 
WHEN 条件1 THEN 结果1或语句1(如果是语句,需要加分号) 
WHEN 条件2 THEN 结果2或语句2(如果是语句,需要加分号)
...
ELSE 结果n或语句n(如果是语句,需要加分号)
END [case](如果是放在begin end中需要加上case,如果放在select后面不需要)

17.2.3 循环结构之LOOP

LOOP循环语句用来重复执行某些语句。LOOP内的语句一直重复执行直到循环被退出(使用LEAVE子句),跳出循环过程。

LOOP语句的基本格式如下:

[loop_label:] LOOP
	循环执行的语句
END LOOP [loop_label]

例:

DECLARE id INT DEFAULT 0;
add_loop:LOOP
	SET id = id +1;
	IF id >= 10 THEN LEAVE add_loop;
	END IF;

END LOOP add_loop;

17.2.4 循环结构之WHILE

WHILE语句创建一个带条件判断的循环过程。WHILE在执行语句执行时,先对指定的表达式进行判断,如果为真,就执行循环内的语句,否则退出循环。WHILE语句的基本格式如下:

[while_label:] WHILE 循环条件  DO
	循环体
END WHILE [while_label];

17.2.5 循环结构之REPEAT

REPEAT语句创建一个带条件判断的循环过程。与WHILE循环不同的是,REPEAT 循环首先会执行一次循环,然后在 UNTIL 中进行表达式的判断,如果满足条件就退出,即 END REPEAT;如果条件不满足,则会就继续执行循环,直到满足退出条件为止。

REPEAT语句的基本格式如下:

[repeat_label:] REPEAT
    循环体的语句
UNTIL 结束循环的条件表达式
END REPEAT [repeat_label]

对比三种循环结构:

1、这三种循环都可以省略名称,但如果循环中添加了循环控制语句(LEAVE或ITERATE)则必须添加名称。

2、 LOOP:一般用于实现简单的"死"循环 WHILE:先判断后执行 REPEAT:先执行后判断,无条件至少执行一次

凡是循环结构,一定具备四个要素

1.初始化条件

2.循环条件

3.循环体

4.迭代条件

LEAVE关键字

相当于java中的break

ITERATE关键字

相当于java中的continue

14.4. 游标

虽然我们也可以通过筛选条件 WHERE 和 HAVING,或者是限定返回记录的关键字 LIMIT 返回一条记录,但是,却无法在结果集中像指针一样,向前定位一条记录、向后定位一条记录,或者是随意定位到某一条记录,并对记录的数据进行处理。

这个时候,就可以用到游标。游标,提供了一种灵活的操作方式,让我们能够对结果集中的每一条记录进行定位,并对指向的记录中的数据进行操作的数据结构。游标让 SQL 这种面向集合的语言有了面向过程开发的能力。

在 SQL 中,游标是一种临时的数据库对象,可以指向存储在数据库表中的数据行指针。这里游标充当了指针的作用,我们可以通过操作游标来对数据行进行操作。

MySQL中游标可以在存储过程和函数中使用。

比如,我们查询了 employees 数据表中工资高于15000的员工都有哪些:

SELECT employee_id,last_name,salary FROM employees
WHERE salary > 15000;

第一步,声明游标

DECLARE cursor_name CURSOR FOR select_statement; 

第二步,打开游标

OPEN cursor_name

第三步,使用游标(从游标中取得数据)

FETCH cursor_name INTO var_name [, var_name] ...

第四步,关闭游标

CLOSE cursor_name

十八.触发器

18.1. 触发器概述

触发器是由事件来触发某个操作,这些事件包括INSERTUPDATEDELETE事件。所谓事件就是指用户的动作或者触发某项行为。如果定义了触发程序,当数据库执行这些语句时候,就相当于事件发生了,就会自动激发触发器执行相应的操作。

18.2. 触发器的创建

CREATE TRIGGER 触发器名称 
{BEFORE|AFTER} {INSERT|UPDATE|DELETE} ON 表名 
FOR EACH ROW 
触发器执行的语句块;

说明:

  • 表名:表示触发器监控的对象。

  • BEFORE|AFTER:表示触发的时间。BEFORE 表示在事件之前触发;AFTER 表示在事件之后触发。

  • INSERT|UPDATE|DELETE:表示触发的事件。

    • INSERT 表示插入记录时触发;

    • UPDATE 表示更新记录时触发;

    • DELETE 表示删除记录时触发。

  • 触发器执行的语句块:可以是单条SQL语句,也可以是由BEGIN…END结构组成的复合语句块。

举例:

DELIMITER //

CREATE TRIGGER before_insert
BEFORE INSERT ON test_trigger 
FOR EACH ROW
BEGIN
	INSERT INTO test_trigger_log (t_log)
	VALUES('before_insert');

END //

DELIMITER ;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值