文章目录
- 1. MySQL你好鸭
- 2. DQL(Data Query Language)的学习
- 2.1 查询表中单个、多个字段
- 2.2 查询表中所有字段
- 2.3 打开数据库
- 2.4 常量值
- 2.5 起别名
- 2.6 DISTINCT - 去重
- 2.7 操作数中有字符串或NULL时
- 2.8 CONCAT - 字符串拼接
- 2.9 IFNULL - 处理NULL数据
- 2.10 关系运算符和逻辑运算符
- 2.11 LIKE - 模糊查询
- 2.12 IN - 存在于
- 2.13 IS NULL
- 2.14 <=> - 安全等于
- 2.15 ORDER BY - 排序查询
- 2.16 字符串函数
- 2.17 数学函数
- 2.18 日期函数
- 2.19 版本号、当前数据库、当前用户
- 2.20 流程控制函数
- 2.21 聚合函数
- 2.22 连接查询
- 3. DML(数据操纵语言)
- 4. DDL(数据定义语言)
1. MySQL你好鸭
1.1 Linux安装MySQL
参考教程
以下操作以 Aliyun Linux 2 操作系统为例进行演示。
1.1.1 安装MariaDB
MariaDB 数据库管理系统是 MySQL 的一个分支,主要由开源社区在维护,采用 GPL 授权许可。开发这个分支的原因之一是:甲骨文公司收购了 MySQL 后,有将 MySQL 闭源的潜在风险,因此社区采用分支的方式来避开这个风险。
MariaDB的目的是完全兼容MySQL,包括API和命令行,使之能轻松成为MySQL的代替品。
安装的命令:
yum install mariadb-server mariadb
1.1.2 查看版本信息
查看版本信息的命令:
mysqladmin --version
1.1.3 启动/停止服务
启动服务的命令:
systemctl start mariadb
其他命令:
systemctl start mariadb #启动MariaDB
systemctl stop mariadb #停止MariaDB
systemctl restart mariadb #重启MariaDB
systemctl enable mariadb #设置开机启动
1.1.4 设置root密码
初始 root 密码为空,可以通过以下命令设置:
mysqladmin -u root password "new_password"
1.1.5 连接到MySQL服务器
设置密码以后,使用如下命令连接 MySQL 服务器:
mysql -u root -p
输入密码即可。
1.2 修改root密码
执行以下命令:
mysqladmin -u root -p原密码 password "新密码"
注意,-p 和原密码之间不要有空格。
1.3 显示所有数据库
show databases;
1.4 进入指定数据库
use 数据库名;
1.5 查看有哪些表
查看当前数据库有哪些表
show tables;
查看指定数据库
show tables from 数据库名;
1.6 查看当前位于哪个数据库
select database();
1.7 查看表的结构
desc 表名;
1.8 查看MySQL版本
select version();
1.9 注释
# 注释文字
-- 注释文字
/* 多行注释 */
1.10 配置DataGrip连接远程服务器
这样,通过 SSH 的方式就可以连接到远程 MySQL 服务器了。
1.11 解决数据库乱码问题
MySQL的默认编码是Latin1,不支持中文,下面将其修改为 utf8mb4。
首先执行:
SHOW VARIABLES LIKE 'character%';
如果看到的结果不是这样,则需要修改配置文件:
修改如下文件:
然后重启 MySQL 服务:
重启以后,再执行:
SHOW VARIABLES LIKE 'character%';
就可以了。
如果此时数据库的编码还是有问题,那么先 DROP 掉当前数据库,重新 CREATE 一个数据库即可。
2. DQL(Data Query Language)的学习
先执行网上下的sql文件:myemployees.sql,便生成了数据库myemployees。
链接:https://pan.baidu.com/s/1skbVEuiFYQRPS5IIG3yACw
提取码:j6je
2.1 查询表中单个、多个字段
SELECT last_name, email
FROM employees;
2.2 查询表中所有字段
SELECT *
FROM employees;
2.3 打开数据库
用在SQL查询语句之前。
USE myemployees;
2.4 常量值
SELECT 100;
SELECT 'yaya';
2.5 起别名
作用:1. 便于理解;2. 如果要查询的字段有重名,使用别名可以区别开。
SELECT last_name AS 姓 -- AS可以省略
FROM employees;
如果别名含有空格:
SELECT last_name AS "last name"
FROM employees;
2.6 DISTINCT - 去重
SELECT DISTINCT department_id
FROM employees;
2.7 操作数中有字符串或NULL时
-- 两个操作数均为数值型,做加法运算
SELECT 100 + 90; -- 190
-- 若操作数为字符型,尝试将字符型转为数值型,继续加法运算
SELECT '100' + 90; -- 190
-- 如果转换失败,则将字符型视为0
SELECT 'yaya' + 90; -- 90
SELECT 'yaya' * 90; -- 0
-- 只要操作数有null,则结果为null
SELECT NULL + 10; -- <null>
SELECT NULL * 10; -- <null>
SELECT NULL - NULL; -- <null>
2.8 CONCAT - 字符串拼接
SELECT CONCAT(last_name, ' ', first_name) AS 姓名
FROM employees;
2.9 IFNULL - 处理NULL数据
如果参数一值为NULL,则返回参数二;否则返回参数一。
SELECT IFNULL(commission_pct, 999)
FROM employees;
2.10 关系运算符和逻辑运算符
SELECT 查询列表 FROM 表名 WHERE 筛选条件;
案例1:查询工资大于12000的员工信息
SELECT *
FROM employees
WHERE salary > 12000;
案例2:查询工资在10000到20000之间的员工信息
SELECT *
FROM employees
WHERE salary >= 10000 AND salary <= 20000;
BETWEEN … AND …
效果同上。(闭区间)
SELECT *
FROM employees
WHERE salary BETWEEN 10000 AND 20000;
2.11 LIKE - 模糊查询
默认不区分大小写
通配符:
百分号——替代0个或多个字符
下划线——替代一个字符
案例1:查询员工名包含“a”的员工信息
SELECT *
FROM employees
WHERE last_name LIKE '%a%';
案例2:查询员工名中第三个字符为n,第五个字符为l
SELECT *
FROM employees
WHERE last_name LIKE '__n_l%';
转义:查询员工名中第二个字符为下划线的
SELECT *
FROM employees
WHERE last_name LIKE '_\_%';
显式转义
使用任何字符当转义符。
SELECT *
FROM employees
WHERE last_name LIKE '_$_%' ESCAPE '$';
2.12 IN - 存在于
案例1:查询员工工种号是IT_PROG、AD_VP之一的
SELECT *
FROM employees
WHERE job_id IN ('IT_PROG', 'AD_VP');
2.13 IS NULL
案例1:查询没有奖金的员工
SELECT *
FROM employees
WHERE commission_pct IS NULL; -- 这里不能用=比较
案例2:查询有奖金的员工
SELECT *
FROM employees
WHERE commission_pct IS NOT NULL;
2.14 <=> - 安全等于
既可以判断普通的值,也可以判断NULL值。
SELECT *
FROM employees
WHERE commission_pct <=> NULL OR commission_pct <=> 0.2;
2.15 ORDER BY - 排序查询
案例1:查询员工信息,按工资从高到低排序
升序排序,则不写DESC。
SELECT *
FROM employees
ORDER BY salary DESC;
案例2:按年薪降序排序
-- 写法一
SELECT *, salary * 12 * (1 + IFNULL(commission_pct, 0)) AS 年薪
FROM employees
ORDER BY salary * 12 * (1 + IFNULL(commission_pct, 0)) DESC;
-- 写法二
SELECT *, salary * 12 * (1 + IFNULL(commission_pct, 0)) AS 年薪
FROM employees
ORDER BY 年薪 DESC;
案例3:先按工资排序,再按员工编号排序
SELECT *
FROM employees
ORDER BY salary DESC, employee_id ASC;
2.16 字符串函数
LENGTH - 字符串长度(字节数)
案例1:按姓名的长度排序
SELECT *, LENGTH(last_name)
FROM employees
ORDER BY LENGTH(last_name);
UPPER/LOWER - 大小写
略。
SUBSTR - 字符串子串
支持中文、索引从1开始。
SELECT SUBSTR('abcdefg', 2); -- bcdefg
SELECT SUBSTR('我是耿耿欧耶', 2); -- 是耿耿欧耶
SELECT SUBSTR('我是耿耿欧耶', 2, 3); -- 是耿耿
INSTR - 返回子串的位置
SELECT INSTR('尔等看好了!', '看好'); -- 3
SELECT INSTR('尔等看好了!', '看好啦'); -- 0
SELECT INSTR('你猜猜看', '猜'); -- 2
TRIM - 去前后空格
略。
LPAD /RPAD - 左对齐和右对齐
SELECT LPAD('耿鸭', 10, '*'); -- ********耿鸭
SELECT LPAD('耿鸭', 10, '*+-'); -- *+-*+-*+耿鸭
SELECT LPAD('我是很长的字符串', 3, '*+-'); -- 我是很
REPLACE - 字符串替换
略。
2.17 数学函数
ROUND - 四舍五入
CEIL - 向上取整
FLOOR - 向下取整
TRUNCATE - 截断小数(取整)
SELECT TRUNCATE(3.1999, 0); -- 3
SELECT TRUNCATE(3.1999, 1); -- 3.1
SELECT TRUNCATE(3.1999, 2); -- 3.19
SELECT TRUNCATE(-3.1999, 0); -- -3
SELECT TRUNCATE(-3.1999, 1); -- -3.1
SELECT TRUNCATE(-3.1999, 2); -- -3.19
MOD - 取模
与%一样。
2.18 日期函数
NOW - 返回当前时间
SELECT NOW(); -- 2020-03-27 09:49:21
CURDATE - 返回日期(不包含时间)
SELECT CURDATE(); -- 2020-03-27
CURTIME - 返回时间(不包含日期)
SELECT CURTIME(); -- 09:50:38
提取日期的各个部分
SELECT YEAR(NOW()); -- 2020
SELECT YEAR('1998-1-1'); -- 1998
SELECT MONTH(NOW()); -- 3
SELECT MONTHNAME(NOW()); -- March
SELECT DAY(NOW()); -- 27
SELECT HOUR(NOW());
SELECT MINUTE(NOW());
SELECT SECOND(NOW());
STR_TO_DATE - 字符串转日期
SELECT STR_TO_DATE('09-13-2019', '%m-%d-%Y'); -- 2019-09-13
SELECT STR_TO_DATE('59:07:40', '%i:%H:%s'); -- 07:59:40
DATE_FORMAT - 日期转字符串
SELECT DATE_FORMAT(NOW(), '%Y年%m月%d日 %H时%i分%s秒'); -- 2020年03月29日 07时36分31秒
2.19 版本号、当前数据库、当前用户
-- 查看版本号
SELECT VERSION(); -- 8.0.19
-- 查看当前数据库
SELECT DATABASE(); -- myemployees
-- 查看当前用户
SELECT USER(); -- root@localhost
2.20 流程控制函数
IF()
SELECT IF(10 > 5, '大', '小'); -- 大
SELECT IF(10 > 15, '大', '小'); -- 小
-- 查询每个员工是否有奖金
SELECT last_name, commission_pct, IF(commission_pct IS NULL, '无奖金', '有奖金')
FROM employees;
CASE()
SELECT last_name,
salary AS 原始工资,
department_id,
CASE department_id
WHEN 30 THEN salary + 100
WHEN 40 THEN salary + 200
WHEN 50 THEN salary + 300
ELSE salary
END AS 新工资
FROM employees;
2.21 聚合函数
SUM - 求和
SELECT SUM(salary)
FROM employees;
AVG - 平均值
MAX - 最大值
MIN - 最小值
COUNT - 统计个数
COUNT统计的是非NULL的个数!
上面5个函数都忽略了NULL值!
SELECT SUM(salary), AVG(salary), MAX(salary), MIN(salary), COUNT(salary)
FROM employees;
与DISTINCT搭配使用
-- 去重以后求和
SELECT SUM(DISTINCT salary), SUM(salary)
FROM employees;
-- 统计不相同的工资数目
SELECT COUNT(DISTINCT salary), COUNT(salary)
FROM employees;
COUNT函数的详细介绍
-- 统计表中有多少行
SELECT COUNT(*)
FROM employees;
SELECT COUNT(1) -- 每一行增加一列,值为1,统计1的数量,就相当于统计行数
FROM employees;
GROUP BY - 分组
WHERE一定放在FROM后面,GROUP BY放在WHERE后面,ORDER BY放最后。
案例1:查询每个工种的最高工资
SELECT job_id, MAX(salary)
FROM employees
GROUP BY job_id;
案例2:查询每个位置上的部门个数
SELECT location_id, COUNT(*)
FROM departments
GROUP BY location_id;
案例3:查询每个部门的平均工资,只统计邮箱中包含a字符的
SELECT department_id, AVG(salary)
FROM employees
WHERE email LIKE '%a%'
GROUP BY department_id;
HAVING - 分组后筛选
案例1:查询哪个部门的员工人数>2
-- 写法一
SELECT department_id, COUNT(*)
FROM employees
GROUP BY department_id
HAVING COUNT(*) > 2;
-- 写法二
SELECT department_id, COUNT(*) cnt
FROM employees
GROUP BY department_id
HAVING cnt > 2;
案例2:查询每个工种有奖金的员工的最高工资>12000的工种
SELECT job_id, MAX(salary)
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
HAVING MAX(salary) > 12000;
案例3:查询领导编号>102的每个领导手下员工最低工资>5000的领导编号,以及最低工资
SELECT manager_id, MIN(salary)
FROM employees
WHERE manager_id > 102
GROUP BY manager_id
HAVING MIN(salary) > 5000;
按多个字段分组
查询每个部门每个工种的员工平均工资
SELECT department_id, job_id, AVG(salary)
FROM employees
GROUP BY department_id, job_id;
分组后排序
查询每个部门每个工种的员工平均工资(按平均工资排序)
SELECT department_id, job_id, AVG(salary)
FROM employees
GROUP BY department_id, job_id
ORDER BY AVG(salary) DESC;
2.22 连接查询
连接查询又称为“多表查询”。
笛卡尔积
SELECT COUNT(*) FROM a;
假设输出12行。
SELECT COUNT(*) FROM b;
假设输出4行。
SELECT COUNT(*) FROM a, b;
输出 12 × 4 = 48 12\times4=48 12×4=48 行。
等值连接
特点:
- 多表等值连接的结果为多表的交集部分
- n表连接,至少需要n-1个连接条件
- 多表的顺序没有要求
- 一般需要为表起别名
案例1:查询员工名和对应的部门名。
SELECT last_name, department_name
FROM employees, departments
WHERE employees.department_id = departments.department_id;
案例2(分组查询):查询每个城市的部门个数。
SELECT city, COUNT(*)
FROM departments d, locations l
WHERE d.location_id = l.location_id
GROUP BY city;
案例3:查询 有奖金 的 每个部门 的 部门名 和 部门的领导编号 和 该部门的最低工资。
SELECT department_name, d.manager_id, MIN(salary)
FROM departments d, employees e
WHERE d.department_id = e.department_id
AND commission_pct IS NOT NULL
GROUP BY department_name, manager_id;
非等值连接
案例:查询员工的工资和工资级别。
(先执行百度云共享中的job_grades.sql)
先查看一下job_grades表的内容:
SELECT first_name, salary, grade_level
FROM employees e, job_grades j
WHERE e.salary BETWEEN j.lowest_sal AND j.highest_sal;
自连接
自己连接自己。
案例:查询 员工名 和 对应的领导名。
SELECT e.employee_id, e.last_name, m.employee_id, m.last_name
FROM employees e, employees m
WHERE e.manager_id = m.employee_id;
内连接(SQL99)
分为等值连接、非等值连接、自连接,和上面差不多,语法有一些区别。
案例1:查询 员工名 部门名。
SELECT last_name, department_name
FROM employees e
INNER JOIN departments d
ON e.department_id = d.department_id;
案例2:查询 姓名 中 包含 e 的 员工名 和 工种名。
SELECT last_name, job_title
FROM employees e
INNER JOIN jobs j
ON e.job_id = j.job_id
WHERE e.last_name LIKE '%e%';
3. DML(数据操纵语言)
3.1 插入 - insert
语法:
INSERT INTO 表名(列名,...) VALUES (值1,...);
3.1.1 经典的插入方式
例如,在 beauty 表中插入一行记录。首先查看 beauty 有哪些字段:
然后使用 insert 语句插入:
INSERT INTO beauty(id, name, sex, borndate, phone, photo, boyfriend_id)
VALUES (99, '耿鸭', '男', '1999-9-9', '123456', NULL, 99);
也可以一次插入多行:
INSERT INTO beauty(id, name, phone)
VALUES (101, '甲', '110'),
(102, '乙', '119'),
(103, '丙', '120');
还可以使用子查询:
INSERT INTO beauty(id, name, phone)
SELECT 105, '猫猫', 'xxx';
相当于把 SELECT 的查询结果对应插入相应的列。
注:
- 字段的值与字段名必须数量相同、一一对应。
- 如果某个字段为空,那么可以不写(即 beauty 之后的括号内不写)。
- 字段的顺序可以调换。
- 可以省略字段名(即省掉 beauty 之后的括号),那么默认是所有字段,字段的顺序与表中字段的顺序一致。
3.1.2 方式二
语法:
INSERT INTO 表名 SET 列名=值,列名=值,...
为空的字段可以不写。
INSERT INTO beauty
SET id=100, name='萨斯给', phone='110';
显然方式一的功能比较多。
3.2 修改 - update
3.2.1 修改单表记录
语法:
UPDATE 表名 SET 列 = 新值,列 = 新值,... WHERE 筛选条件;
注:
- 如果不加 WHERE 字句,则修改表中所有记录。
案例:
-- 案例1:修改beauty表中所有姓周的女神的电话
UPDATE beauty SET phone = '12306'
WHERE name LIKE '周%';
3.2.2 修改多表记录(级联更新)
语法:
UPDATE 表1 别名,表2 别名 SET 列 = 值,... WHERE 连接条件 AND 筛选条件;
SQL99 语法:
UPDATE 表1 别名 INNER|LEFT|RIGHT JOIN 表2 别名 ON 连接条件 SET 列 = 值,... WHERE 筛选条件;
案例:
-- 案例1:修改张无忌的女朋友的手机号
UPDATE boys bo
INNER JOIN beauty b ON bo.id = b.boyfriend_id
SET b.phone = '114'
WHERE bo.boyName = '张无忌';
-- 案例2:修改没有男朋友的女神的男朋友编号都为2
UPDATE boys bo
RIGHT JOIN beauty b ON bo.id = b.boyfriend_id
SET b.boyfriend_id = 2
WHERE bo.id IS NULL;
3.3 删除 - delete/truncate
3.3.1 delete
单表删除
语法:
DELETE FROM 表名 WHERE 筛选条件;
注:如果不加 WHERE 子句,则删除表中所有记录。
案例:
-- 案例1:删除手机号以9结尾的女神信息
DELETE FROM beauty
WHERE phone LIKE '%9';
多表删除(级联删除)
语法:
DELETE 表1或表2的别名 FROM 表1 别名,表2 别名 WHERE 连接条件 AND 筛选条件;
SQL99 语法:
DELETE 表1或表2的别名 FROM 表1 别名 INNER|LEFT|RIGHT JOIN 表2 别名 ON 连接条件 WHERE 筛选条件;
注:DELETE 后面跟几个表的别名就删除几个表的记录。
3.3.2 truncate
语法:
TRUNCATE TABLE 表名;
删除表中所有记录。
删库跑路!
3.3.3 比较(重点)
- truncate 效率比 delete 高。
- 假如要删除的表中有自增长列,如果用 delete 删除后再插入数据,自增长列的值从断点开始;如果用 truncate 删除后再插入数据,自增长列的值从1开始。
- truncate 无返回值,delete 有返回值。
- 事务:truncate 删除不能回滚,delete 删除可以回滚。
4. DDL(数据定义语言)
用于数据库和表的管理。
- 创建:create
- 修改:alter
- 删除:drop
4.1 数据库的管理
4.1.1 创建数据库
创建数据库,存在则报错:
CREATE DATABASE 库名;
创建数据库,无则创建,有则无事发生:
CREATE DATABASE IF NOT EXISTS 库名;
4.1.2 库的修改
一般不修改数据库的名称,为了防止各种问题。
修改数据库的字符集:
ALTER DATABASE 库名 CHARACTER SET gbk;
4.1.3 删除数据库
删除数据库,不存在则报错:
DROP DATABASE 库名;
删除数据库,有则删除,无则无事发生:
DROP DATABASE IF EXISTS 库名;
4.2 表的管理
4.2.1 表的创建(重点)
语法:
CREATE TABLE (
列名 列的类型(长度) 约束,
列名 列的类型(长度) 约束,
......
);
案例:
CREATE TABLE book (
id INT, # 编号
name VARCHAR(20), # 书名
price DOUBLE, # 价格
author_id VARCHAR(20), # 作者编号
publish_date DATE # 出版日期
);
DESC book;
可以看出,如果不指定是否为空,那么默认是可以为空的。
4.2.2 表的修改
修改字段名和字段类型
语法:
ALTER TABLE 表名 CHANGE COLUMN 字段名 新字段名 新类型;
修改字段的类型
语法:
ALTER TABLE 表名 MODIFY COLUMN 字段名 新类型;
增加新字段
语法:
ALTER TABLE 表名 ADD COLUMN 新字段名 类型;
删除字段
语法:
ALTER TABLE 表名 DROP COLUMN 字段名;
修改表名
语法:
ALTER TABLE 原表名 RENAME TO 新表名;
4.2.3 表的删除
语法:
DROP TABLE 表名;
4.2.4 通用的写法
建库
DROP DATABASE IF EXISTS 库名;
CREATE DATABASE 库名;
建表
DROP TABLE IF EXISTS 表名;
CREATE TABLE 表名(...);
4.2.5 表的复制
仅仅复制表的结构
语法:
CREATE TABLE 新表名 LIKE 原表名;
复制表的结构和数据
语法:
CREATE TABLE 新表名 SELECT * FROM 原表名;
仅仅复制一部分结构
很巧妙的方法:
CREATE TABLE 新表名
SELECT 字段名1,字段名2
FROM 原表名
WHERE 1=2;
4.3 数据类型
4.3.1 数值型
注:
- 默认情况下是有符号整型,如果想使用无符号,在类型后面加“UNSIGNED”,如“INT UNSIGNED”。
- 如果插入的值越界了,那么会抛出异常,不会插入(至少在我的机器上是这样)。
注:
- D 表示小数点后保留的位数(十进制),而整数部分的最大位数为 M - D。
4.3.2 字符型
较短的文本 - char, varchar
注:
- 这里是“最多字符数”,不是字节数。
- char 代表固定长度的字符,varchar 代表可变长度的字符。
- char 耗费空间多,但是效率比 varchar 高。
示例:
CREATE TABLE test_enum (
sex ENUM('男', '女')
);
INSERT INTO test_enum VALUE ('男');
INSERT INTO test_enum VALUE ('女');
INSERT INTO test_enum VALUE ('妖'); -- 异常
略。
较长的文本 - text, blob
4.3.3 日期型
示例:
CREATE TABLE test_date (
t0 DATE,
t1 DATETIME,
t2 TIMESTAMP
);
INSERT INTO test_date VALUES (NOW(), NOW(), NOW());
SELECT * FROM test_date;
4.4 约束
4.4.1 非空约束 - NOT NULL
用于保证该字段的值不为 NULL。
示例:
CREATE TABLE student (
id INT PRIMARY KEY,
name VARCHAR(20) NOT NULL,
sex ENUM('男', '女'),
seat INT UNIQUE,
age INT DEFAULT 18
);
可将多个字段组合成一个主键,唯一键同理:
CREATE TABLE major (
id INT,
major_name VARCHAR(20),
PRIMARY KEY (id, major_name)
);
4.4.2 默认约束 - DEFAULT
用于保证该字段有默认值。
示例:见 4.4.1 节。
4.4.3 主键约束 - PRIMARY KEY
用于保证该字段的值具有唯一性,并且非空。
示例:见 4.4.1 节。
4.4.4 唯一约束 - UNIQUE
用于保证该字段的值具有唯一性,可以为空,但是只能有一个 NULL 值的记录。
示例:见 4.4.1 节。
4.4.5 检查约束 - CHECK
MySQL中不支持。
4.4.6 外键约束 - FOREIGN KEY
用于限制两个表的关系,保证该字段的值来自另一个表关联列的值。
示例:
DROP TABLE IF EXISTS student;
DROP TABLE IF EXISTS major;
CREATE TABLE major (
id INT PRIMARY KEY,
major_name VARCHAR(20) NOT NULL
);
CREATE TABLE student (
id INT PRIMARY KEY,
name VARCHAR(20) NOT NULL,
major_id INT,
FOREIGN KEY (major_id) REFERENCES major(id)
);
注:被参考的外键(如本例 major 表的 id)一定要是键(主键、唯一键)。
4.4.7 主键和唯一键的区别
- 唯一键可为空,主键不可为空。
- 一个表中,唯一键可有多个,主键至多只能有一个。
- 可将多个字段组合作为一个主键,唯一键同理。
4.4.8 现有字段增加约束
方式一:直接重新定义某个字段(列级约束)
ALTER TABLE 表名 MODIFY COLUMN 字段名 类型 约束;
方式二:给某个字段添加约束(表级约束)
ALTER TABLE 表名 ADD 约束 (字段名);
4.4.9 现有字段删除约束
方式一:直接重新定义某个字段
同 4.4.8 节。
4.4.10 自增长列
DROP TABLE IF EXISTS student;
CREATE TABLE student (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20)
);
-- 两种插入方法
INSERT INTO student (name) VALUES ('haha');
INSERT INTO student VALUES (NULL, 'xixi');
注:
- 一个表只能有一个自增长列,且它必须是一个键(主键、唯一键)。
- 自增长列的类型必须为数值型(整型、浮点型)。