一、 Ubuntu下安装MySQL
安装教程是在Ubuntu20.04
下进行的,安装的MySQL版本为8.0.27
。
1.1 安装
sudo apt install mysql-server mysql-client
在输入密码后,再输入yes
即可开始安装。
安装完成后,通过运行命令mysql -V
查看版本号:
lyons@ubuntu:~$ mysql -V
mysql Ver 8.0.27-0ubuntu0.20.04.1 for Linux on x86_64 ((Ubuntu))
验证MySQL服务正在运行,命令行下输入:
sudo service mysql status
如果正在运行,则会显示:
● mysql.service - MySQL Community Server
Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2021-10-27 10:27:59 CST; 9h ago
Main PID: 6179 (mysqld)
Status: "Server is operational"
Tasks: 39 (limit: 4599)
Memory: 348.9M
CGroup: /system.slice/mysql.service
└─6179 /usr/sbin/mysqld
10月 27 10:27:59 ubuntu systemd[1]: Starting MySQL Community Server...
10月 27 10:27:59 ubuntu systemd[1]: Started MySQL Community Server.
1.2 配置MySQL的安全性
略
1.3 以root用户登录
如果你想以 root 身份登录 MySQL 服务器,便于使用其他的程序。可以将验证方法从auth_socket
修改成mysql_native_password
。
本地实验使用 mysql_native_password
lyons@ubuntu:~$ mysql -uroot -p
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1698 (28000): Access denied for user 'root'@'localhost'
1.4 修改密码
将用户admin
的登录密码修改为mysql321
:
ALTER USER 'admin'@'localhost' IDENTIFIED WITH mysql_native_password BY 'mysql321';
1.5 撤销用户授权
# 查看用户的权限
show grants for 'admin'@'localhost';
# 撤销用户的权限
# 用户有什么权限就撤销什么
revoke all privileges on *.* from 'admin'@'localhost';
1.6 删除用户
drop user 'admin'@'localhost';
注:MySQL 8.0版本和5.0部分命令有所改掉,上述语法都是在8.0版本下运行通过的;请务必检查自己的MySQL版本号。
二、MySQL预备知识
在正式学习MySQL之前,我们先来了解一下SQL语句的书写规范以及命名规则等。
2.1 SQL书写规范
在写SQL语句时,要求按照如下规范进行:
-
SQL 语句要以分号(;)结尾
-
SQL 不区分关键字的大小写 ,这对于表名和列名同样适用。
-
插入到表中的数据是区分大小写的。例如,数据Computer、COMPUTER 或computer,三者是不一样的。
-
常数的书写方式是固定的,在SQL 语句中直接书写的字符串、日期或者数字等称为常数。常数的书写方式如下所示。
- SQL 语句中含有字符串的时候,需要像’abc’这样,使用单引号(’)将字符串括起来,用来标识这是一个字符串。
- SQL 语句中含有日期的时候,同样需要使用单引号将其括起来。日期的格式有很多种(‘26 Jan 2010’ 或者’10/01/26’ 等)。
- 在SQL 语句中书写数字的时候,不需要使用任何符号标识,直接写成1000 这样的数字即可。
-
单词之间需要用半角空格或者换行来分隔。
-
SQL中的注释主要采用
--
和/* ... */
的方式,第二种方式可以换行。在MySQL下,还可以通过#
来进行注释。
2.2 命名规则
- 在数据库中,只能使用半角英文字母、数字、下划线(_)作为数据库、表和列的名称 。
- 名称必须以半角英文字母作为开头。
- 名称不能重复,同一个数据库下不能有2张相同的表。
2.3. 数据类型
MySQL 支持所有标准 SQL 数值数据类型,包括:
(1)数值类型
数值包含的类型如下:
-
整型数据:
TINYINT
、INTEGER
、SMALLINT
、MEDIUMINT
、DECIMAL
、NUMERIC
和BIGINT
。 -
浮点型数据:
DECIMAL
、FLOAT
、REAL
和DOUBLE PRECISION
)。
其中,关键字INT
是INTEGER
的同义词,关键字DEC是的同义词。
不同关键字的主要区别就是表示的范围或精度不一样。具体如下表:
类型 | 大小 | 范围(有符号) | 范围(无符号) | 用途 |
---|---|---|---|---|
TINYINT | 1 Bytes | (-128,127) | (0,255) | 小整数值 |
SMALLINT | 2 Bytes | (-32 768,32 767) | (0,65 535) | 大整数值 |
MEDIUMINT | 3 Bytes | (-8 388 608,8 388 607) | (0,16 777 215) | 大整数值 |
INT或INTEGER | 4 Bytes | (-2 147 483 648,2 147 483 647) | (0,4 294 967 295) | 大整数值 |
BIGINT | 8 Bytes | (-9,223,372,036,854,775,808,9 223 372 036 854 775 807) | (0,18 446 744 073 709 551 615) | 极大整数值 |
FLOAT | 4 Bytes | (-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) | 0,(1.175 494 351 E-38,3.402 823 466 E+38) | 单精度 浮点数值 |
DOUBLE | 8 Bytes | (-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 双精度 浮点数值 |
DECIMAL | 对DECIMAL(M,D) ,如果M>D,为M+2否则为D+2 | 依赖于M和D的值 | 依赖于M和D的值 | 小数值 |
(2)日期和时间类型
表示时间值的日期和时间类型为DATETIME
、DATE
、TIMESTAMP
、TIME
和YEAR
。具体如下表:
类型 | 大小 ( bytes) | 范围 | 格式 | 用途 |
---|---|---|---|---|
DATE | 3 | 1000-01-01/9999-12-31 | YYYY-MM-DD | 日期值 |
TIME | 3 | ‘-838:59:59’/‘838:59:59’ | HH:MM:SS | 时间值或持续时间 |
YEAR | 1 | 1901/2155 | YYYY | 年份值 |
DATETIME | 8 | 1000-01-01 00:00:00/9999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS | 混合日期和时间值 |
TIMESTAMP | 4 | 1970-01-01 00:00:00/2038结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07 | YYYYMMDD HHMMSS | 混合日期和时间值,时间戳 |
(3)字符串类型
字符串类型指CHAR
、VARCHAR
、BINARY
、VARBINARY
、BLOB
、TEXT
、ENUM
和SET
。具体如下表:
类型 | 大小 | 用途 |
---|---|---|
CHAR | 0-255 bytes | 定长字符串 |
VARCHAR | 0-65535 bytes | 变长字符串 |
TINYBLOB | 0-255 bytes | 不超过 255 个字符的二进制字符串 |
TINYTEXT | 0-255 bytes | 短文本字符串 |
BLOB | 0-65 535 bytes | 二进制形式的长文本数据 |
TEXT | 0-65 535 bytes | 长文本数据 |
MEDIUMBLOB | 0-16 777 215 bytes | 二进制形式的中等长度文本数据 |
MEDIUMTEXT | 0-16 777 215 bytes | 中等长度文本数据 |
LONGBLOB | 0-4 294 967 295 bytes | 二进制形式的极大文本数据 |
LONGTEXT | 0-4 294 967 295 bytes | 极大文本数据 |
-
char
声明的是定长字符串。若实际中字符串长度不足,则会在末尾使用空格进行填充至声明的长度。 -
varchar
声明的是可变长字符串。存储过程中,只会按照字符串的实际长度来存储,但会多占用一位来存放实际字节的长度。
三、数据库的基本操作
首先,我们来学习在MySQL下如何操作数据库。
3.1 数据库的创建
通过CREATE
命令,可以创建指定名称的数据库,语法结构如下:
CREATE DATABASE [IF NOT EXISTS] <数据库名称>;
MySQL 的数据存储区将以目录方式表示 MySQL 数据库,因此数据库名称必须符合操作系统的文件夹命名规则,不能以数字开头,尽量要有实际意义。
MySQL下不运行存在两个相同名字的数据库,否则会报错。如果使用IF NOT EXISTS
(可选项),可以避免此类错误。
示例:
-- 创建名为shop的数据库。
CREATE DATABASE shop;
3.2 数据库的查看
- 查看所有存在的数据库
SHOW DATABASES [LIKE '数据库名'];;
LIKE
从句是可选项,用于匹配指定的数据库名称。LIKE
从句可以部分匹配,也可以完全匹配。
示例:
SHOW DATABASES;
-- 结果如下:
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| shop |
| sys |
+--------------------+
5 rows in set (0.01 sec)
-- %表示任意0个或多个字符,可匹配任意类型和长度的字符。
SHOW DATABASES LIKE 'S%';
-- 结果如下
+---------------+
| Database (S%) |
+---------------+
| shop |
| sys |
+---------------+
2 rows in set (0.00 sec)
- 查看创建的数据库
SHOW CREATE DATABASE <数据库名>;
示例:
SHOW CREATE DATABASE shop;
-- 或者
SHOW CREATE DATABASE shop \G
-- 结果如下
*************************** 1. row ***************************
Database: shop
Create Database: CREATE DATABASE `shop` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */
1 row in set (0.00 sec)
CHARACTER SET utf8mb4
表示编码字符集为utf8mb4
。
3.3 选择数据库
在操作数据库前,必须指定所要操作的数据库。通过USE
命令,可以切换到对应的数据库下。
USE <数据库名>
示例:
-- 切换到数据库shop下。
USE shop;
-- 结果如下
Database changed
3.4 删除数据库
通过DROP
命令,可以将相应数据库进行删除。
DROP DATABASE [IF EXISTS] <数据库名>
其中,IF EXISTS
为可选性,用于防止数据库不存在时报错。
示例:
DROP DATABASE shop;
SHOW DATABASES;
考虑到后面表的操作都是shop数据库下,在实验完DROP
删除数据库命令后,请从新创建数据库shop并通过USE
命令切换到该数据库下。
四、表的基本操作
表相当于文件,表中的一条记录就相当于文件的一行内容,不同的是,表中的一条记录有对应的标题,称为表的字段。
4.1 表的创建
创建表的语法结构如下:
CREATE TABLE <表名> (<字段1> <数据类型> <该列所需约束>,
<字段2> <数据类型> <该列所需约束>,
<字段3> <数据类型> <该列所需约束>,
<字段4> <数据类型> <该列所需约束>,
.
.
.
<该表的约束1>, <该表的约束2>,……);
示例:
-- 创建一个名为Product的表
CREATE TABLE Product(
product_id CHAR(4) NOT NULL,
product_name VARCHAR(100) NOT NULL,
product_type VARCHAR(32) NOT NULL,
sale_price INT,
purchase_price INT,
regist_date DATE,
PRIMARY KEY (product_id)
);
在第二章中,我们介绍过不同的数据类型:
-
CHAR
为定长字符,这里CHAR
旁边括号里的数字表示该字段最长为多少字符,少于该数字将会使用空格进行填充。 -
VARCHAR
表示变长字符,括号里的数字表示该字段最长为多少字符,存储时只会按照字符的实际长度来存储,但会使用额外的1-2字节来存储值长度。
简单介绍一下该语句中出现的约束条件,约束条件在后面会详细介绍:
PRIMARY KEY
:主键,表示该字段对应的内容唯一且不能为空。NOT NULL
:在NULL
之前加上了表示否定的NOT
,表示该字段不能输入空白。
通过SHOW TABLES
命令来查看当前数据库下的所有的表名:
SHOW TABLES;
-- 结果如下
+----------------+
| Tables_in_shop |
+----------------+
| Product |
+----------------+
1 rows in set (0.00 sec)
通过DESC <表名>
来查看表的结构:
DESC Product;
-- 结果如下
+----------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+-------+
| product_id | char(4) | NO | PRI | NULL | |
| product_name | varchar(100) | NO | | NULL | |
| product_type | varchar(32) | NO | | NULL | |
| sale_price | int | YES | | NULL | |
| purchase_price | int | YES | | NULL | |
| regist_date | date | YES | | NULL | |
+----------------+--------------+------+-----+---------+-------+
6 rows in set (0.00 sec)
4.2 表的删除
删除表的语法结构如下:
DROP TABLE <表名>;
-- 例如:DROP TABLE Product;
说明:通过DROP
删除的表示无法恢复的,在删除表的时候请谨慎。
4.3 表的更新
通过ALTER TABLE
语句,我们可以对表字段进行不同的操作,下面通过示例来具体学习用法。
示例:
- 创建一张名为Student的表
CREATE TABLE Student(
id INT PRIMARY KEY,
name CHAR(15)
);
DESC student;
-- 结果如下
+-------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| id | int | NO | PRI | NULL | |
| name | char(15) | YES | | NULL | |
+-------+----------+------+-----+---------+-------+
2 rows in set (0.00 sec)
-
更改表名
通过
RENAME
命令,将表名从Student => Students。
ALTER TABLE Student RENAME Students;
-
插入新的字段
通过
ADD
命令,新增字段sex和age。
-- 不同的字段通过逗号分开
ALTER TABLE Students ADD sex CHAR(1), ADD age INT;
其它插入技巧:
-- 通过FIRST在表首插入字段stu_num
ALTER TABLE Students ADD stu_num INT FIRST;
-- 指定在字段sex后插入字段height
ALTER TABLE Students ADD height INT AFTER sex;
DESC Students;
-- 结果如下
+---------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+----------+------+-----+---------+-------+
| stu_num | int | YES | | NULL | |
| id | int | NO | PRI | NULL | |
| name | char(15) | YES | | NULL | |
| sex | char(1) | YES | | NULL | |
| height | int | YES | | NULL | |
| age | int | YES | | NULL | |
+---------+----------+------+-----+---------+-------+
6 rows in set (0.00 sec)
-
字段的删除
通过
DROP
命令,可以对不在需要的字段进行删除。
-- 删除字段stu_num
ALTER TABLE Students DROP stu_num;
-
字段的修改
通过
MODIFY
修改字段的数据类型。
-- 修改字段age的数据类型
ALTER TABLE Students MODIFY age CHAR(3);
通过CHANGE
命令,修改字段名或类型
-- 修改字段name为stu_name,不修改数据类型
ALTER TABLE Students CHANGE name stu_name CHAR(15);
-- 修改字段sex为stu_sex,数据类型修改为int
ALTER TABLE Students CHANGE sex stu_sex INT;
DESC Students;
-- 结果如下
+----------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+----------+------+-----+---------+-------+
| id | int | NO | PRI | NULL | |
| stu_name | char(20) | YES | | NULL | |
| stu_sex | int | YES | | NULL | |
| height | int | YES | | NULL | |
| age | char(3) | YES | | NULL | |
+----------+----------+------+-----+---------+-------+
5 rows in set (0.00 sec)
4.4 表的查询
通过SELECT
语句,可以从表中取出所要查看的字段的内容:
SELECT <字段名>, ……
FROM <表名>;
如要直接查询表的全部字段:
SELECT *
FROM <表名>;
其中,**星号(*)**代表全部字段的意思。
示例:
-
建表并插入数据
在MySQL中,我们通过
INSERT
语句往表中插入数据,该语句在后面会详细介绍,该小节的重点是学会使用SELECT
。
-- 向Product表中插入数据
INSERT INTO Product VALUES
('0001', 'T恤衫', '衣服', 1000, 500, '2009-09-20'),
('0002', '打孔器', '办公用品', 500, 320, '2009-09-11'),
('0003', '运动T恤', '衣服', 4000, 2800, NULL),
('0004', '菜刀', '厨房用具', 3000, 2800, '2009-09-20'),
('0005', '高压锅', '厨房用具', 6800, 5000, '2009-01-15'),
('0006', '叉子', '厨房用具', 500, NULL, '2009-09-20'),
('0007', '擦菜板', '厨房用具', 880, 790, '2008-04-28'),
('0008', '圆珠笔', '办公用品', 100, NULL,'2009-11-11')
;
- 查看表的内容
-- 查看表的全部内容
SELECT *
FROM Product;
-- 结果如下
+------------+--------------+--------------+------------+----------------+-------------+
| product_id | product_name | product_type | sale_price | purchase_price | regist_date |
+------------+--------------+--------------+------------+----------------+-------------+
| 0001 | T恤衫 | 衣服 | 1000 | 500 | 2009-09-20 |
| 0002 | 打孔器 | 办公用品 | 500 | 320 | 2009-09-11 |
| 0003 | 运动T恤 | 衣服 | 4000 | 2800 | NULL |
| 0004 | 菜刀 | 厨房用具 | 3000 | 2800 | 2009-09-20 |
| 0005 | 高压锅 | 厨房用具 | 6800 | 5000 | 2009-01-15 |
| 0006 | 叉子 | 厨房用具 | 500 | NULL | 2009-09-20 |
| 0007 | 擦菜板 | 厨房用具 | 880 | 790 | 2008-04-28 |
| 0008 | 圆珠笔 | 办公用品 | 100 | NULL | 2009-11-11 |
+------------+--------------+--------------+------------+----------------+-------------+
8 rows in set (0.00 sec)
-- 查看部分字段包含的内容
SELECT
product_id,
product_name,
sale_price
FROM Product;
-- 结果如下
+------------+--------------+------------+
| product_id | product_name | sale_price |
+------------+--------------+------------+
| 0001 | T恤衫 | 1000 |
| 0002 | 打孔器 | 500 |
| 0003 | 运动T恤 | 4000 |
| 0004 | 菜刀 | 3000 |
| 0005 | 高压锅 | 6800 |
| 0006 | 叉子 | 500 |
| 0007 | 擦菜板 | 880 |
| 0008 | 圆珠笔 | 100 |
+------------+--------------+------------+
8 rows in set (0.00 sec)
-
对查看的字段从新命名
通过
AS
语句对展示的字段另起别名,这不会修改表内字段的名字。
SELECT
product_id AS ID,
product_type AS TYPE
FROM Product;
-- 结果如下
+------+--------------+
| ID | TYPE |
+------+--------------+
| 0001 | 衣服 |
| 0002 | 办公用品 |
| 0003 | 衣服 |
| 0004 | 厨房用具 |
| 0005 | 厨房用具 |
| 0006 | 厨房用具 |
| 0007 | 厨房用具 |
| 0008 | 办公用品 |
+------+--------------+
8 rows in set (0.00 sec)
设定汉语别名时需要使用双引号(")括起来,英文字符则不需要。
SELECT
product_id AS "产品编号",
product_type AS "产品类型"
FROM Product;
-
常数的查询
SELECT
子句中,除了可以写字段外,还可以写常数。
SELECT
'商品' AS string,
'2009-05-24' AS date,
product_id,
product_name
FROM Product;
-- 结果如下
+--------+------------+------------+--------------+
| string | date | product_id | product_name |
+--------+------------+------------+--------------+
| 商品 | 2009-05-24 | 0001 | T恤衫 |
| 商品 | 2009-05-24 | 0002 | 打孔器 |
| 商品 | 2009-05-24 | 0003 | 运动T恤 |
| 商品 | 2009-05-24 | 0004 | 菜刀 |
| 商品 | 2009-05-24 | 0005 | 高压锅 |
| 商品 | 2009-05-24 | 0006 | 叉子 |
| 商品 | 2009-05-24 | 0007 | 擦菜板 |
| 商品 | 2009-05-24 | 0008 | 圆珠笔 |
+--------+------------+------------+--------------+
8 rows in set (0.00 sec)
-
删除重复行
在
SELECT
语句中使用DISTINCT
可以去除重复行。
SELECT
DISTINCT regist_date
FROM Product;
-- 结果如下
+-------------+
| regist_date |
+-------------+
| 2009-09-20 |
| 2009-09-11 |
| NULL |
| 2009-01-15 |
| 2008-04-28 |
| 2009-11-11 |
+-------------+
6 rows in set (0.01 sec)
在使用DISTINCT
时,NULL
也被视为一类数据。NULL
存在于多行中时,会被合并为一条NULL
数据。
还可以通过组合使用,来去除列组合重复的数据。DISTINCT
关键字只能用在第一个列名之前。
SELECT
DISTINCT product_type, regist_date
FROM Product;
-- 结果如下,列出了所有的组合
+--------------+-------------+
| product_type | regist_date |
+--------------+-------------+
| 衣服 | 2009-09-20 |
| 办公用品 | 2009-09-11 |
| 衣服 | NULL |
| 厨房用具 | 2009-09-20 |
| 厨房用具 | 2009-01-15 |
| 厨房用具 | 2008-04-28 |
| 办公用品 | 2009-11-11 |
+--------------+-------------+
7 rows in set (0.00 sec)
-
指定查询条件
首先通过
WHERE
子句查询出符合指定条件的记录,然后再选取出SELECT
语句指定的列,语法结构如下:
SELECT <字段名>, ……
FROM <表名>
WHERE <条件表达式>;
示例:
SELECT product_name
FROM Product
WHERE product_type = '衣服';
-- 结果如下
+--------------+
| product_name |
+--------------+
| T恤衫 |
| 运动T恤 |
+--------------+
2 rows in set (0.01 sec)
注意,WHERE
子句要紧跟在FROM
子句之后。
4.5 表的复制
表的复制可以将表结构与表中的数据全部复制,或者只复制表的结构。