推荐课程:B站韩顺平老师的Mysql课程
一、MySQL的基础概念
- MySQL,就是一个数据库管理系统(DBMS),这个管理系统可以管理多个数据库,每个数据库下又有多张表
- MySQL,数据库,数据表的关系如下
- SQL语句分类
1)数据定义语句:DDL [CREATE 表/库 …]
2)数据操作语句:DML [添加 INSERT,删除 DELETE,修改 UPDATE]
3)数据查询语句:DQL [查询 SELECT]
4)数据控制语句:DCL [管理数据库 grant …]
二、数据库操作语句
- 常用的操作数据库的语句
# 创建数据库语句,字符集默认为utf8,校对规则默认为utf8_general_ci
CREATE DATABASE 数据库名称 [CHARACTER SET 字符集] [COLLATE 校对规则];
# 显示数据库语句
SHOW DATABASES;
# 显示数据库创建语句
SHOW CREATE DATABASE 数据库名称;
# 删除数据库语句
DROP DATABASE 数据库名称;
# 备份数据库, DOS命令下执行
# mysqldump -u root -p -B 数据库1 [数据库2 ...] > [备份文件存放路径]
# 下面语句的意思是将数据库db01备份,并将备份文件放到 D:/Mysql/db01.sql
mysqldump -u root -p -B db01 > D:/Mysql/db01.sql
# 需要先切换到备份文件存放的目录 D:/Mysql/
# 然后连接MYSQL服务器,执行以下命令
SOURCE db01.sql
# 备份数据表, DOS命令下执行
# mysqldump -u root -p 数据库名称 表1 [表2 ...] > [备份文件存放路径]
# 下面语句的意思是将数据库db01的table01表备份
# 将备份文件放到 D:/Mysql/db01_table01.sql
mysqldump -u root -p db01 table01 > D:/Mysql/db01_table01.sql
# 连接MYSQL服务器,执行以下命令
USE db01;
SOURCE D:/Mysql/db01_table01.sql
- 根据备份文件恢复数据库
方式1:切换到备份文件存放的目录 -> 连接到Mysql -> 根据备份文件恢复数据库
方式2:连接到Mysql -> 根据备份文件的全路径恢复数据库
- 根据备份文件恢复数据表
- 字符集
utf8支持的字符的最大长度为3字节,当遇到4字符的"🐖"等符号时,无法正确存储,会报错。
utf8mb4支持的字符的最大长度为4字节,基本可以存现有的所有字符。
当字符集为ut8是,无法存储该符号"🐖"
当字符修改为utf8mb8后,可正确存储
- 校对规则说明
编码选择utf8时,校对规则utf8_general_ci不区分大小写,而utf8_bin区分大小写;
编码选择utf8mb4时,校对规则utf8mb4_0900_ai_ci不区分大小写,而utf8mb4_bin区分大小写。
- 反引号的使用
# 当创建的数据库名称,表名称,字段名称刚好为关键字是,需要添加反引号``
CREATE DATABASE `CREATE`;
三、数据表操作语句
- 常用的数据表操作语句
# 创建数据表
CREATE TABLE 表名 (
字段1 数据类型 [NOT NULL] [DEFAULT 默认值] [PRIMARY KEY] [...]
字段2 数据类型 [...]
...
) CHARSET 字符集 COLLATE 校对规则 ENGINE 引擎;
# 创建表table03,包含字段id和name,字符集、校对规则、引擎都使用默认配置
CREATE TABLE table03 (
id int PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
# 新增列/字段
ALTER TABLE 表名 ADD 字段名 数据类型 [...];
ALTER TABLE table03 ADD gender CHAR(1) NOT NULL DEFAULT '';
# 修改列
ALTER TABLE 表名 MODIFY 字段名 数据类型 [...];
# 将table03的name字段数据类型修改为VARCHAR(32),并且要求非空,默认为''
ALTER TABLE table03 MODIFY name VARCHAR(32) NOT NULL DEFAULT '';
# 删除列
ALTER TABLE 表名 DROP 字段名;
# 删除table03的gender字段
ALTER TABLE table03 DROP gender;
# 修改表的字符集
ALTER TABLE 表名 CHARACTER SET 字符集;
# 修改表table03的字符集为utf8mb4
ALTER TABLE table03 CHARACTER SET utf8mb4;
# 查看表结构
DESC 表名;
# 查看table03的表结构
DESC table03;
# 修改字段名称
ALTER TABLE 表名 CHANGE 原字段名 新字段名 数据类型 [选项 ...];
# 修改table03的字段name的名称为user_name;
ALTER TABLE table03 CHANGE `name` `user_name` VARCHAR(32) NOT NULL DEFAULT '';
# 修改表名
RENAME TABLE 当前表名 TO 新表名;
# 修改表table03的名称为table3
RENAME TABLE table03 to `table3`;
# 删除表
DROP TABLE 表名;
# 删除table3表
DROP TABLE table3;
四、数据类型
4.1、整数类型
bit(M)
:位类型,需要指定位数,M的范围为1-64
tinyInt
:1字节,带符号的范围是-128 ~ 127,无符号的范围是0~255
smallInt
:2字节,带符号的范围是-2^15 ~ 2^15 - 1,无符号的范围是 0 ~ 2^16 - 1
mediumInt
:3字节,带符号的范围是-2^23 ~ 2^23 - 1,无符号的范围是 0 ~ 2^24 - 1
int
:4字节,带符号的范围是-2^31 ~ 2^31 - 1,无符号的范围是 0 ~ 2^32 - 1
bigInt
:8字节,带符号的范围是-2^63 ~ 2^63 - 1,无符号的范围是 0 ~ 2^64 - 1
- 在满足业务需求的条件下,应该选择占用空间更新的整数类型
- 如果没有指定unsigned,默认是带符号整型,
int unsigned
表示使用无符号的int型
注意:
对于上述除
bit
外的所有整数类型,当我们定义int(8)
时,括号中的8并不是指定数据的长度或范围。
当我们使用上图一的SQL创建数据表user
时,INT
后面的8是毫无作用的。只有加上如图二的ZEROFILL
关键字,且当id
字段的值小于8位时,MySQL
在返回数据时会在字段前面填充零。例如,插入时设置字段id
的值为68
,加上ZEROFILL
关键字后,真正存储到文件的仍然是68
,但返回时却是00000068
。
4.2、浮点类型
float:单精度浮点型,4字节,精度只能保留到小数点后4位,四舍五入保留4位
double:双精度浮点型,8字节,精度可以精确到小数点后14位,四舍五入保留14位
decimal(M,D):大数类型,
M表示整数部分和小数部分的最大十进制位数,D表示小数点后的十进制位数,
M最大为65,默认为10,D最大为30,默认为0;
如M=16,D=6时,最大保存数字为9999999999.999999
- decimal所占字节的计算
decimal使用二进制格式进行存储,该格式将9个十进制的数字打包为4个字节,当无法被9整除,剩余的十进制位数所占字节数如下表所示
十进制位数 | 所占字节 |
---|---|
1~2 | 1 |
3~4 | 2 |
5~6 | 3 |
7~8 | 4 |
例1:decimal(16,8)
整数部分占16-8=8位,小数部分占8位
整数部分需要4个字节,小数部分也需要4个字节,总共占8个字节
例2:decimal(16,6)
整数部分占16-6=10位,小数部分占6位
整数部分需要4+1=5个字节,小数部分需要3个字节,总共占8个字节
4.3、字符串类型
char:固定长度字符串,最大长度为255字符
varchar:可变长度字符串,最大长度为65535字节
【当编码为utf8mb4时,每个字符占4字节,varchar可存储的最大长度为16383字符】
【当编码为utf8时,每个字符占3字节,varchar可存储的最大长度为21844字符】
【当编码为gbk时,每个字符占2字节,varchar可存储的最大长度为32766字符】
【varchar会有1-3个字节用于记录字符串真正的长度】
char与varchar的使用细节
长度问题
varchar(4) 与char(4)中的数字4都是代表字符数,
varchar的最大长度是根据字符集编码的改变而改变的,
char的最大长度固定为255
定长与变长问题
char(4)是定长的,固定占用4字符的大小,当存储的只是两字符的
aa
时,MySQL会使用空格在字符串尾部填充到4字符,且在返回数据时时,尾部的空格会被去掉。
varchar(4)是变长的,如果插入的是两字符的’aa’,那么只会占用两字符的空间,需要注意的是,varchar还有1-3个字节用于存放长度,那么总共占用的空间便是(实际数据大小+1-3字节)
CHAR与VARCHAR的选用
使用CHAR的情况:
1)存储的数据是定长的字符,例如MD5(固定为32位),身份证号(固定为18位)
2)存储的数据经常需要修改
使用VARCHAR的情况:
1)存储的数据是变长的字符
2)存储的数据很少修改
查询速度:CHAR快于VARCHAR
4.4、日期类型
date
:4字节,年月日
datetime
:8字节,年月日 时分秒
timestamp
:4字节,年月日 时分秒,受时区影响,只能存储1970 ~ 2037之间的时间
- MySQL能存储的最小时间粒度为秒。
- 当数据类型为
TIMESTAMP
或DATETIME
时,可以用CURRENT_TIMESTAMP
作为默认(MySQL5.6
及更高版本),MySQL会自动生成记录插入的确切时间。- TIMESTAMP是UTC时间戳,与时区相关。
DATETIME
的存储格式是一个YYYYMMDD HH:MM:SS
的整数,与时区无关。- 对于创建时间和更新时间字段,阿里规约推荐使用
DATETIME
类型,但若是开发的程序运行年限不超过2038年,那么可以选择占用空间更小的TIMESTAMP
类型。
五、Insert语句
5.1、语法
INSERT INTO 表名(column1, column2, ...)
VALUES(value1, value2, ...)
[,values(value1, value2, ...), ...];
5.2、使用细节
- 插入的数据类型应与字段数据类型一致
- 插入的数据的长度应在字段规定的范围内
- 在values中列出的数据位置必须与被加入的列的排列位置相对应
- 字符和日期型数据应包含在单引号中
- 当列不允许为空且没有默认值时,必须给列插入值
六、Update语句
6.1、语法
# 如果没有where字句,那么将对表中的所有数据行进行修改
UPDATE 表名 SET column1=value1 [, column2=value2, ...]
[WHERE condition]
七、Delete语句
7.1、语法
# 如果没有where字句,那么将会删除表中所有数据
DELETE FROM 表名 [WHERE condition]
7.2、使用细节
- DELETE语句不能删除某一列的值,要删除某一列的值可以用UPDATE语句将其设为NULL
- DELETE语句只能删除记录,不能删除表,要删除表应使用
DROP TABLE 表名
;
八、Select语句
8.1、测试数据
CREATE TABLE student(
id INT NOT NULL DEFAULT 1, `name` VARCHAR(20) NOT NULL DEFAULT '', chinese FLOAT NOT NULL DEFAULT 0.0, english FLOAT NOT NULL DEFAULT 0.0, math FLOAT NOT NULL DEFAULT 0.0
);
INSERT INTO student(id,`name`,chinese,english,math)
VALUES(1,'曹操',89,78,90);
INSERT INTO student(id,`name`,chinese,english,math)
VALUES(2,'张飞',67,98,56);
INSERT INTO student(id,`name`,chinese,english,math)
VALUES(3,'司马懿',87,78,77);
INSERT INTO student(id,`name`,chinese,english,math)
VALUES(4,'赵云',82,84,67);
INSERT INTO student(id,`name`,chinese,english,math)
VALUES(5,'赵子龙',55,85,45);
INSERT INTO student(id,`name`,chinese,english,math)
VALUES(6,'诸葛亮',75,65,30);
CREATE TABLE dept( /*部门表*/
deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
dname VARCHAR(20) NOT NULL DEFAULT "",
loc VARCHAR(13) NOT NULL DEFAULT ""
);
INSERT INTO dept VALUES(10, 'ACCOUNTING', 'NEW YORK'),
(20, 'RESEARCH', 'DALLAS'),
(30, 'SALES', 'CHICAGO'),
(40, 'OPERATIONS', 'BOSTON');
/*员工表*/
CREATE TABLE emp(
empno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, /*编号*/
ename VARCHAR(20) NOT NULL DEFAULT "", /*名字*/
job VARCHAR(9) NOT NULL DEFAULT "",/*工作*/
mgr MEDIUMINT UNSIGNED ,/*上级编号*/
hiredate DATE NOT NULL,/*入职时间*/
sal DECIMAL(7,2) NOT NULL,/*薪水*/
comm DECIMAL(7,2) ,/*红利 奖金*/
deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0 /*部门编号*/
);
INSERT INTO emp VALUES
(7369, 'SMITH', 'CLERK', 7902, '1990-12-17', 800.00,NULL , 20),
(7499, 'ALLEN', 'SALESMAN', 7698, '1991-2-20', 1600.00, 300.00, 30),
(7521, 'WARD', 'SALESMAN', 7698, '1991-2-22', 1250.00, 500.00, 30),
(7566, 'JONES', 'MANAGER', 7839, '1991-4-2', 2975.00,NULL,20),
(7654, 'MARTIN', 'SALESMAN', 7698, '1991-9-28',1250.00,1400.00,30),
(7698, 'BLAKE','MANAGER', 7839,'1991-5-1', 2850.00,NULL,30),
(7782, 'CLARK','MANAGER', 7839, '1991-6-9',2450.00,NULL,10),
(7788, 'SCOTT','ANALYST',7566, '1997-4-19',3000.00,NULL,20),
(7839, 'KING','PRESIDENT',NULL,'1991-11-17',5000.00,NULL,10),
(7844, 'TURNER', 'SALESMAN',7698, '1991-9-8', 1500.00, NULL,30),
(7900, 'JAMES','CLERK',7698, '1991-12-3',950.00,NULL,30),
(7902, 'FORD', 'ANALYST',7566,'1991-12-3',3000.00, NULL,20),
(7934,'MILLER','CLERK',7782,'1992-1-23', 1300.00, NULL,10);
#工资级别表
CREATE TABLE salgrade
(
grade MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, /*工资级别*/
losal DECIMAL(17,2) NOT NULL, /* 该级别的最低工资 */
hisal DECIMAL(17,2) NOT NULL /* 该级别的最高工资*/
);
INSERT INTO salgrade VALUES (1,700,1200);
INSERT INTO salgrade VALUES (2,1201,1400);
INSERT INTO salgrade VALUES (3,1401,2000);
INSERT INTO salgrade VALUES (4,2001,3000);
INSERT INTO salgrade VALUES (5,3001,9999);
8.2、语法
# 基本语法,单表查询
SELECT [DISTINCT] *|{列名 [AS] [别名], 列名 [AS] [别名], ...}
FROM 表名
[ GROUP BY 列名 [HAVING condition] ]
[ ORDER BY 列名 [ASC|DESC] ]
[ LIMIT 从结果集的第几条记录开始 取多少条记录]
# where字句中的比较运算符
大于 >
大于等于 >=
小于 <
小于等于 <=
等于 =
不等于 != <>
大于等于value1且小于等于value2 BETWEEN value1 AND value2
属于列表中包含的值 IN (value1, value2, ...)
模糊查询 [NOT] like
判断是否为空,判断是否为空不能用等号 IS [NOT] NULL
# where字句中的逻辑运算符
多个条件同时成立 and
多个条件中一个成立 or
取相反结果 not
8.3、函数
8.3.1、统计函数
count(*|列名)
:统计结果有多少条记录sum(列名)
:对某一列进行求和avg(列名)
:求某一列的平均值max(列名)
:查询某一列的最大值min(列名)
:查询某一列的最小值
统计函数作用在非数值列上时不会报错,但是没有意义
8.3.2、字符串相关函数
charset(str)
:返回字符串的字符集concat(str1, [str2, ...])
:拼接字符串instr(str, substr)
:返回substri在str中出现的位置,没有则返回0ucase(str)
:转换为大写lcase(str)
:转换为小写left(str, len)
:取str的前len个字符length(str)
:返回字符串长度,以字节为单位replace(str, str1, str2)
:用str2替换字符串str中的str1strcmp(str1, str2)
:逐字比较两字符串的大小substring(str, index [,length])
:从index位置开始截取字符串,未指定length则取到末尾,字符串的第一个字符的下标为1ltrim(str)
:去除字符串前端的空白字符rtrim(str)
:去除字符串后端的空白字符
8.3.3、数学相关函数
abs(num)
:取绝对值bin(num)
:十进制转二进制ceiling(num)
:向上取整floor(num)
:向下取整bin(num)
:十进制转二进制hex(num)
:十进制转十六进制conv(num, from_base, to_base)
:from_base进制数转成to_base进制数format(num, count)
:四舍五入保留count为小数least(num1, num2, [num3, ..,])
:求最小值mod(num, n)
:求余,相当于num%nrand([seed])
:随机数,返回0 <= res <1之间的小数,指定seed种子时,会返回重复的随机数
8.3.4、日期相关函数
current_date()
:返回当前日期current_time()
:返回当前时间now()
:返回当前日期+时间current_timestamp()
:返回当前时间戳unix_timestamp()
:返回1970到当前的秒数from_unixtime(seconds, dateformat)
:将1970到当前的秒数转到指定的日期格式“%Y-%m-%d %H:%i:%s”,select from_unixtime(unix_timestamp(), '%Y-%m-%d %H:%i:%s');
获取当前日期与时间date(datetime)
:单号datetime的日期部分date_add(date, interval value type)
:在date的日期上添加一个时间,type可以是year、month、day、hour等date_sub(date, interval value type)
:在date的日期上减少一个时间,type可以是year、month、day、hour等datediff(date1, date2)
:返回两个日期的差,结果是天数timediff(time1, time2)
:返回两个时间的差,结果是多少小时多少分钟多少秒
8.3.5、系统函数
user()
:当前登录用户database()
: 当前使用的数据库md5(str)
:生成str的md5加密32位字符串
8.3.6、流程控制函数
if(exp1, exp2, exp3)
:如果exp1为true,则返回表达式exp2的结果,否则返回表达式exp3的结果ifnull(exp1, exp2)
:如果exp1不为空,则返回exp1,否则返回exp2case when exp1 then exp2 when exp3 then exp4 else exp5
:当exp1为true,则返回exp2,否则,则进行下一层判断,如果exp3为true,则返回exp4,否则返回exp5
8.4、查询实操
- 学生表相关查询
# 查询student表中所有学生的所有信息
SELECT * FROM `student`;
# 查询student表中所有学生的姓名和英语成绩
SELECT `name`, english FROM `student`;
# 查询student表中所有的英语成绩,并去重
SELECT DISTINCT english FROM `student`;
# 查询统计每个学生的总分
SELECT `name`, (chinese+math+english) total FROM `student`;
# 查询数学成绩大于等于60且小于等于90的学生
SELECT `name`, math FROM `student` WHERE math BETWEEN 60 AND 90;
SELECT `name`, math FROM `student` WHERE math >= 60 AND math <= 90;
# 查询数学成绩大于80或者语文成绩大于80分的学生
SELECT `name`, math, chinese
FROM `student`
WHERE math > 80 OR chinese > 80;
# 查询姓名以'赵'开头的学生信息
SELECT * FROM `student` WHERE `name` LIKE '赵%';
# 查询数学成绩大于70的学生,且按数学成绩降序
SELECT `name`, math FROM `student`
WHERE math > 70
ORDER BY math DESC;
# 查询所有学生信息,并按总分从低到高排序
SELECT *,(math+english+chinese) total
FROM `student`
ORDER BY (math+english+chinese);
SELECT *,(math+english+chinese) as total
FROM `student`
ORDER BY total;
- 员工表相关查询
# 查询每个部门的平均工资和最高工资以及最低工资
SELECT deptno, AVG(sal) avg_sal, MAX(sal) max_sal, MIN(sal) min_sal
FROM emp
GROUP BY deptno;
# 查询每个部门每种岗位的平均工资和最高工资以及最低工资
SELECT deptno, AVG(sal) avg_sal, MAX(sal) max_sal, MIN(sal) min_sal
FROM emp
GROUP BY deptno, job;
# 查询平均工资低于2000的部门号和平均工资
SELECT deptno, AVG(sal) as avg_sal
FROM emp
GROUP BY deptno
HAVING avg_sal < 2000;
# 查询emp表中ename所使用的字符集
SELECT CHARSET(ename) FROM emp limit 1;
# 查询1992.1.1之后入职的员工信息
SELECT * FROM emp WHERE hiredate > '1992-01-01';
# 查询名字第三个字符为O的员工的姓名和工资
SELECT ename, sal FROM emp WHERE ename like '__O%';
# 查询没有上级的员工
SELECT * FROM emp WHERE mgr IS NULL;
# 按照工资从低到高显示雇员信息
SELECT * FROM emp ORDER BY sal;
# 按照部门号升序而工资降序显示雇员信息
SELECT * FROM emp ORDER BY deptno ASC, sal DESC;
# 按照员工编号升序,每页3天,显示第一页,第二页,第三页
# 开始位置start = (当前页-1) * 每页记录数页面
SELECT * FROM emp ORDER BY empno LIMIT 0, 3; # 第一页
SELECT * FROM emp ORDER BY empno LIMIT 3, 3; # 第二页
SELECT * FROM emp ORDER BY empno LIMIT 6, 3; # 第三页
# 显示每种岗位的雇员总数,平均工资
SELECT job, count(*), avg(sal) FROM emp GROUP BY job;
# 显示雇员总数已经获得补助的雇员数
# count(列)时不会统计为NULL的记录
SELECT count(*) AS 雇员总数, count(comm) FROM emp 获得补助雇员数;
SELECT
(SELECT count(*) FROM emp) AS 雇员总数,
(SELECT count(*) FROM emp WHERE comm IS NOT NULL) 获得补助雇员数;
# 显示管理者的总人数
SELECT count(DISTINCT mgr) FROM emp;
# 显示部门号为10的员工名称,部门号,部门名以及工资
SELECT ename, emp.deptno, dname, sal
FROM emp, dept
WHERE emp.deptno = 10
AND emp.deptno = dept.deptno;
# 显示各个员工的姓名,工资,部门名,以及工资级别
SELECT e.ename, d.dname, e.sal, s.grade, s.losal, s.hisal
FROM emp e, dept d, salgrade s
WHERE e.deptno = d.deptno
AND e.sal BETWEEN s.losal AND s.hisal;
# 显示员工姓名及其上级的名字
SELECT e1.ename 员工姓名, e2.ename 上级姓名
FROM emp e1, emp e2
WHERE e1.mgr = e2.empno;
# 显示与SMITH同一部门的所有员工
SELECT * FROM emp where deptno =
(SELECT deptno FROM emp where ename = 'SMITH');
# 查询每个部门的最高工资员工的姓名、部门号、工资、入职时间
SELECT e.ename, e.deptno, e.sal, e.hiredate
FROM emp as e,
(SELECT deptno, max(sal) max_sal FROM emp GROUP BY deptno) as t
WHERE e.deptno = t.deptno AND e.sal = t.max_sal;
# 显示工资比部门30的所有员工的工资高的员工信息
SELECT * FROM emp
WHERE sal > (SELECT max(sal) FROM emp where deptno = 30);
SELECT * FROM emp
WHERE sal > ALL(SELECT sal FROM emp where deptno = 30);
# 显示工资比部门30的任一员工的工资高的员工信息,排除部门30的员工
SELECT * FROM emp
WHERE deptno != 30
AND sal > (SELECT min(sal) FROM emp where deptno = 30);
SELECT * FROM emp
WHERE deptno != 30
AND sal > ANY(SELECT sal FROM emp where deptno = 30);
# 查询与ALLEN部门相同且工作也相同的员工信息,排除ALLEN本人
SELECT * FROM emp
WHERE (deptno, job) = (
SELECT deptno, job FROM emp where ename = 'ALLEN')
AND ename != 'ALLEN';
# 显示每个部门的部门号,部门名称,位置,员工人数
SELECT d.deptno, d.dname, d.loc, t.emp_count
FROM dept as d,
(SELECT deptno, count(*) emp_count FROM emp GROUP BY deptno) as t
WHERE d.deptno = t.deptno;
# 复制表结构, tab_emp新建表,emp存在的表
CREATE TABLE tab_emp LIKE emp;
# 将emp表中的数据复制到tab_emp
INSERT INTO tab_emp
SELECT * FROM emp;
# 按部门编号升序显示部门编号、部门名称以及员工的姓名和工作,同时显示没有员工的部门
# 左连接,以左表为主,显示左表中的所有记录,尽管右边中没有匹配的数据
# 右连接,以表右为主,显示右表中的所有记录,尽管左边中没有匹配的数据
SELECT t.deptno, t.dname, e.ename, e.job
FROM dept as t
LEFT JOIN emp as e on t.deptno = e.deptno;
SELECT t.deptno, t.dname, e.ename, e.job
FROM emp as e
RIGHT JOIN dept as t on t.deptno = e.deptno;
九、约束
9.1、主键 primary key
- 一张表最多只能有一个主键,但是可以是复合主键
- 主键列不能为空
- 主键列的值必须唯一
# 单值主键
CREATE tab_01 (
id int primary key,
name varchar(64)
);
CREATE tab_02 (
id int,
name varchar(64),
primary key(id)
);
# 复合主键
CREATE tab_03 (
id int,
name varchar(64),
primary key(id, name)
);
9.2、唯一约束 unique
- 如果字段只有unique约束没有非空约束,可以该字段可以有多个null
- 一张表中可以有多个unique约束
CREATE tab_04 (
id int,
name varchar(64) unique
);
9.3、非空 not null
- 字段不能为空
- 一个表可以有多个not null约束
CREATE tab_05 (
id int not null,
name varchar(64) unique not null
);
9.4、自增长 auto_increment
- 自增长一般和主键配合使用
- 自增长也可以不配合主键使用,但是必须配合unique
- 自增长的字段类型一般为整型,浮点型一般不使用自增
- 自增默认从1开始,可通过
alter table 表名 auto_increment = 起始值
修改起始值
CREATE tab_06 (
id int primary key auto_increment,
name varchar(64)
);