步骤/目录:
1.mysql特性与基础概念,及安装
2.进入mysql命令行与基本设置
3.mysql命令行的基础命令
4.增删库、表及注意事项
5.表内数据的基础增删查改
6.LIKE 与模糊查找

本文首发于个人博客https://lisper517.top/index.php/archives/42/,转载请注明出处。
本文的目的是对MySQL进行简单介绍,便于用mysql存储爬虫爬取到的数据。
本文写作日期为2022年9月2日。本文主要整理自 runoob教程 。进阶学习mysql可以参考《MySQL必知必会》、《高性能MySQL》等其他书籍,github上有收集这些CS书的仓库;或者查看笔者后续的文章。

1.mysql特性与基础概念,及安装

除了mysql,还有redis等各种数据库(或者mysql的亲兄弟mariadb等各种sql),它们是为了高速存储数据而出现的。mysql是一种关系性数据库,从上到下,它的构成是:各数据库(database) - 各张表格(table) - 每张表格由行和列组成,列有列名,每一行存储一个条目/记录,每一列的数据类型相同 。另外,mysql中还有主键和索引的概念,每一行记录的主键都不同(其他列可能相同),所以主键可以用于区分每一行记录;索引,类似书籍的目录,用于快速访问数据。

mysql支持大型数据库,单张表的上限主要和操作系统允许的最大文件有关,一般来说,一张表占4GB就差不多了,再高可能有一些性能上的问题。

最后,mysql是开源的,目前是被Oracle买下。

在安装mysql上,笔者建议尽量用docker-mysql的方式安装,可参考 docker-mysql官网 ,或笔者之前的文章。一个基础的docker-compose模板如下:

version: "3.9"

services:
  mysql:
    image: mysql:8.0.29
    environment:
      MYSQL_ROOT_PASSWORD: mysqlpasswd
    ports:
      - "53306:3306"
    command:
      - mysqld
      - --character-set-server=utf8mb4
    volumes:
      - /docker/mysql/data/mysql:/var/lib/mysql
      - /docker/mysql/conf/mysql:/etc/mysql/conf.d
      - /docker/mysql/backup/mysql:/backup
    logging:
      driver: syslog
    restart: always

注意更改一下 MYSQL_ROOT_PASSWORD: mysqlpasswd 这里的密码和 - "53306:3306" 这里的端口(不建议用默认的3306端口)。

2.进入mysql命令行与基本设置

使用命令: mysql -h 127.0.0.1 -P 3306 -uroot -p 可以mysql里的root用户身份登录mysql, -h 参数指定mysql服务器端的ip, -P 指定端口, -u 指定登录用户(如果用root以外的其他用户登,可用 -u 其他用户名 的格式。注意登录的用户不是linux系统里的用户,而是mysql数据库里的用户), -p 指定密码登录,之后输入密码即可。如果是本机、默认的3306端口(mysql默认使用3306端口),则前两个参数可以省略。最后,登录其他机器上的mysql服务器时要注意登录的用户是否允许远程登录(docker-mysql则没有这个问题)。

如果使用docker-mysql,根据 docker-mysql官网 的描述,将自己的mysql配置文件夹挂载到容器的 /etc/mysql/conf.d 文件夹,如果该文件夹里有任何cnf结尾的文件都会覆盖docker-mysql的默认配置。另外,docker-mysql的默认配置文件为容器里的 /etc/mysql/my.cnf 。关于配置方面,笔者几乎没有更改过,所以这方面了解的不多。

mysql -h 127.0.0.1 -P 3306 -uroot -p 登录到mysql命令行后,可以新建其他用户。比较推荐的是用GRANT命令:

GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
ON TUTORIALS.*
TO 'zara'@'localhost'
IDENTIFIED BY 'zara123';

这条命令的第一行是为新建的用户赋予权限。这里赋予了该用户查询、插入、更新、删除数据,及新建、删除数据库/表的权限。也可以自行增加或删除权限,或者用 ALL PRIVILEGES 指代所有权限。
第二行限定该用户只对TUTORIALS这个database下的所有表有这些权限。
第三行指定用户名为zara、登录地点限于从本机登录(当然,对docker-mysql无效)。
最后一行指定zara用户的密码为zara123。
REVOKE 可剥夺用户的选项,语法和 GRANT 是一样的,只是把 TO 换成 FROM

3.mysql命令行的基础命令

mysql命令对大小写不敏感,但笔者建议,自己随便查查的时候可以用全小写,但写到python里的还是建议把所有mysql的关键字大写,以后阅读的时候更容易区分。另外,所有的命令最后都以 ; 结尾,只有少数简单的命令(如 USE 数据库名 )等可以不加 ; ,笔者写的时候有时会省略,自己写的时候记得尽量加上。

SHOW DATABASES 显示所有数据库的名字;
USE 数据库名 选择要操作的数据库(database);
SHOW TABLES 显示该数据库下所有表名;
SHOW COLUMNS FROM 数据表名DESCRIBE 数据表名 显示表的各列是什么数据类型等信息;
SHOW INDEX FROM 数据表名 显示数据表的详细索引;
SHOW TABLE STATUS [FROM 数据库名] [LIKE "模式"] [\G] 可输出数据库的性能、统计信息, [] 里括起来的是可选项。注意 \G 也可以起 ; 的作用,添加这个选项就不加 ;

4.增删库、表及注意事项

CREATE DATABASE 数据库名 来创建一个新的库;更保险的做法是 CREATE DATABASE IF NOT EXISTS 数据库名
DROP DATABASE 数据库名 删除数据库。

创建表则更为复杂,因为要指定每一列的变量类型。mysql中大致有数值、时间、字符串这三种类型的变量,具体见下:
数值(分有符号和无符号)

名称          占用字节  表示范围
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    10的+-38次方级
DOUBLE        8 Bytes    10的+-308次方级
DECIMAL       对DECIMAL(M,D) ,如果M>D,为M+2否则为D+2    依赖于M和D的值

另外还有 BIT位 、 REAL实数 等数值。

时间(分为日期和时间)

名称     占用字节           范围                                                格式
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:01'UTC 到 '2038-01-19 03:14:07'UTC    YYYY-MM-DD hh:mm:ss

字符串(分二进制形式和字符形式)

名称          占用字节                   用途
CHAR        0-255 bytes               定长字符串
VARCHAR     0-65535 bytes             变长字符串
TINYTEXT    0-255 bytes                 短文本字符串
TEXT        0-65 535 bytes            长文本数据
MEDIUMTEXT  0-16 777 215 bytes        中等长度文本数据
LONGTEXT    0-4 294 967 295 bytes     极大文本数据
TINYBLOB    0-255 bytes               不超过 255 个字符的二进制字符串
BLOB        0-65 535 bytes            二进制形式的长文本数据
MEDIUMBLOB  0-16 777 215 bytes        二进制形式的中等长度文本数据
LONGBLOB    0-4 294 967 295 bytes     二进制形式的极大文本数据

另外还有BINARY、VARBINARY等。
对于汉字,用UTF-8编码时占3个字节、用GBK时占2个字节;VARCHAR(n)表示无论汉字或英文,都能存入n个字符(所以占用字节长度会变化,称为 VAR CHAR )。
一般来说,经常变化的字段用VARCHAR,定长、不超过255字节的用CHAR(不够长度的部分mysql在存储时会用空格补齐),偶尔用TEXT(TEXT不能有默认值)。最常用的就是VARCHAR。

创建数据表示需要指定每列的数据类型,还要指定主键。例句如下:

CREATE TABLE IF NOT EXISTS `test`(
`no` INT UNSIGNED AUTO_INCREMENT,
`title` VARCHAR(100) NOT NULL DEFAULT "unknown",
`created_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`no`)
)ENGINE=InooDB DEFAULT CHARSET=utf8;

反引号(就是键盘上ESC下面那个键)起到引号的作用(为了避免有时可能这些名字和mysql关键字冲突,但是尽量勿用关键字做表名、列名); UNSIGNED 为无符号; AUTO_INCREMENT 说明这列的数据是自动增加的(要注意,如果有些行被删除了后再新建行,后面的行 no 值是从被删除的行开始算的,也就是说一个 no 被用过一次后就不会再用,即使对应的行被删除); NOT NULL 指定这一列不能为空(应该用"0"或其他值代替NULL,可提高查询性能,这里用的是"unknown"); DEFAULT 指定默认值; CURRENT_TIMESTAMP 则是该行被创建时的时间戳。 ENGINE=InooDB 指定存储引擎, DEFAULT CHARSET=utf8 指定默认编码(这两个也可以不指定,现在mysql默认引擎就是InooDB,默认编码则可输入 STATUS; 查看)。一般创建表的时候就指定默认编码,笔者使用的docker-compose中有:

    command:
      - mysqld
      - --character-set-server=utf8mb4

mysql默认编码为Latin1,要换成utf8或GBK才能存储中文。

删除表就用 DROP TABLE 表名 即可。

5.表内数据的基础增删查改

INSERT 向表内插入数据:

INSERT INTO 表名(
列名1, 列名2, 列名3...) VALUES
(值1, 值2, 值3...);

可向表内插入一行数据。插入的值是字符串时,使用单引号或双引号括起来。如果某一列有默认值或者是自动生成的,可以忽略、不用写出列名和值。
下面则是添加多行数据:

INSERT INTO 表名(
列名1, 列名2, 列名3...) VALUES
(值1, 值2, 值3...),
(值1, 值2, 值3...),
(值1, 值2, 值3...),
...;

查找数据用 SELECT ,最基本的是 SELECT * FROM 表名 ,返回表内的所有行,其中 * 表示匹配所有列。一般格式为:

SELECT 列名1, 列名2, ...
FROM 表名
[WHERE Clause]
[LIMIT n]
[OFFSET m];

中括号内的都是可选项。 WHERE 从句用来限定条件, LIMIT 限制返回的记录数, OFFSET 指定开始查询的行数(偏移量), LIMIT m,nLIMIT n OFFSET m 的简写(从第几条开始,返回多少条结果)。
在高级查询中,可以从不止一个表中查询数据,表名间用 , 分隔,搭配 WHERE 使用。实际上,删查改一般都要用 WHERE 限定范围。

mysql中的比较符: = 为等于, <>!= 为不等,此外还有 ><>=<= 。另外, BINARY 可以区分大小写:

SELECT * FROM 表名 WHERE BINARY 列名="字符串";

改数据用 UPDATE ,一般格式如下:

UPDATE 表名 SET 列名1=值1, 列名2=值2 [WHERE Clause]

比如,把符合条件的行的列值+1:

UPDATE test SET int_data=int_data+1

又或者用mysql函数:

UPDATE test SET str_data=REPLACE(str_data,"旧字符串","新字符串")

上述命令将该列所有数据内的旧字符串替换为新字符串(部分替换)。

删除记录用 DELETE ,一般格式为:

DELETE FROM 表名 [WHERE Clause]

不加 WHERE 时,会删除所有行。但是,如同之前提到的,如果列中有 AUTO_INCREMENT ,下次再加新行时会从断点继续,就是说新行的自增列不会从1开始。

另外,mysql中的删除其实有三个关键字: DELETEDROPTRUNCATE ,第三个的使用方式:

TRUNCATE 表名

可以把 TRUNCATE 看作是不带 WHEREDELETE FROM ,只用于删除表中的全部数据,优点是执行更快一些;DROP 是把表也给删了,速度最快。

6.LIKE 与模糊查找

前面已经介绍过了, WHERE 从句中可以使用 = 等符号。有时要只想匹配部分字符串,可以使用 LIKE ,或 %_ 通配符。另外mysql也可以使用re,见后续文章。
LIKE 可以替代 =

WHERE 列名1 LIKE 条件1

比如:

WHERE field1 LIKE "%com%"

只要某行的field1列中含连续的 com 三个字符,就符合条件。如果改成 _com_ ,就是指必须是5个字符,中间三个为 com 。也就是说, % 匹配任意个数(包括0个)的任意字符, _ 匹配单个任意字符。
另外, LIKE 里的条件类似re,也有 [] (括号内所列的任意一个字符)、 [^] (非括号内的任意一个字符),如:

LIKE "[abc]"

表示匹配单个字符,这个字符为 abcLIKE "[^abc]" 则表示不能是 abc
在中括号内,用 [] 括起来表示原本的通配符,即 [[%]abc][[_]abc][[[]]abc](匹配 [) 。

到这里为止,mysql的基础已经讲解完毕,其实本文的内容对于爬虫中使用mysql几乎够用了,在下一篇文章中将会讲解进阶的内容。

标签: mysql

添加新评论