安装和使用
安装 MariaDB/MySQL 时的文档
Installing MariaDB/MySQL system tables in ‘/var/lib/mysql’ …
OK
To start mysqld at boot time you have to copy
support-files/mysql.server to the right place for your system
PLEASE REMEMBER TO SET A PASSWORD FOR THE MariaDB root USER !
To do so, start the server, then issue the following commands:
‘/usr/bin/mysqladmin’ -u root password ‘new-password’
‘/usr/bin/mysqladmin’ -u root -h cuiluyuan-pc password ‘new-password’
Alternatively you can run:
‘/usr/bin/mysql_secure_installation’
which will also give you the option of removing the test
databases and anonymous user created by default. This is
strongly recommended for production servers.
See the MariaDB Knowledgebase at http://mariadb.com/kb or the
MySQL manual for more instructions.
You can start the MariaDB daemon with:
cd ‘/usr’ ; /usr/bin/mysqld_safe —datadir=’/var/lib/mysql’
You can test the MariaDB daemon with mysql-test-run.pl
cd ‘/usr/mysql-test’ ; perl mysql-test-run.pl
Please report any problems at http://mariadb.org/jira
The latest information about MariaDB is available at http://mariadb.org/.
You can find additional information about the MySQL part at:
http://dev.mysql.com
Consider joining MariaDB’s strong and vibrant community:
https://mariadb.org/get-involved/
安装 MySQL 的教程
Install and configure Mariadb/MySQL on Archlinux
数据库的基本操作
进入数据库
mysql -u root -p
退出
exit
廖雪峰教程
关系模型
表的每一行称为记录(Record),记录是一个逻辑意义上的数据。
表的每一列称为字段(Column),同一个表的每一行记录都拥有相同的若干字段。
字段定义了数据类型(整型、浮点型、字符串、日期等),以及是否允许为NULL。注意NULL表示字段数据不存在。一个整型字段如果为NULL不表示它的值为0,同样的,一个字符串型字段为NULL也不表示它的值为空串''
△ 通常情况下,字段应该避免允许为NULL。不允许为NULL可以简化查询条件,加快查询速度,也利于应用程序读取数据后无需判断是否为NULL。
例如,在一个班级里
班级表
| ID | 名称 | 班主任 |
|---|---|---|
| 201 | 二年级一班 | 王老师 |
| 202 | 二年级二班 | 李老师 |
学生表
| ID | 姓名 | 班级ID | 性别 | 年龄 |
|---|---|---|---|---|
| 1 | 小明 | 201 | M | 9 |
| 2 | 小红 | 202 | F | 8 |
| 3 | 小军 | 202 | M | 8 |
| 4 | 小白 | 201 | F | 9 |
- 一个班级对应一个老师,班级表和教师表就是”一对一“的关系
- 在数据库中关系主要通过主键和外键来维护的
主键
- 对于关系表,有个很重要的约束,就是任意两条记录不能重复。
- 不能重复不是指两条记录不完全相同,而是指能够通过某个字段唯一区分出不同的记录,这个字段被称为主键。
- 对主键的要求,最关键的一点是:记录一旦插入到表中,主键最好不要再修改,因为主键是用来唯一定位记录的,修改了主键,会造成一系列的影响。
选区主键的一个基本原则:不使用任何业务相关的字段作为主键,因此,身份证号、手机号、邮箱地址这些看上去可以唯一的字段,均不可用作主键。
作为主键最好是完全业务无关的字段,我们一般把这个字段命名为id。常见的可作为id字段的类型有:
- 自增整数类型:数据库会在插入数据时自动为每一条记录分配一个自增整数,这样我们就完全不用担心主键重复,也不用自己预先生成主键;
- 全局唯一GUID类型:使用一种全局唯一的字符串作为主键,类似
8f55d96b-8acc-4636-8cb8-76bf8abc2f57。GUID算法通过网卡MAC地址、时间戳和随机数保证任意计算机在任意时间生成的字符串都是不同的,大部分编程语言都内置了GUID算法,可以自己预算出主键。 - 对于大部分应用来说,通常自增类型的主键就能满足需求。我们在
students表中定义的主键也是BIGINT NOT NULL AUTO_INCREMENT类型
! 如果使用INT自增类型,那么当一张表的记录数超过2147483647(约21亿)时,会达到上限而出错。使用BIGINT自增类型则可以最多约922亿亿条记录。
联合主键
关系数据库实际上还允许通过多个字段唯一标识记录,即两个或更多的字段都设置为主键,这种主键被称为联合主键。
对于联合主键,允许一列有重复,只要不是所有主键列都重复即可:
| id_num | id_type | other columns… |
|---|---|---|
| 1 | A | … |
| 2 | A | … |
| 2 | B | … |
如果我们把上述表的id_num和id_type这两列作为联合主键,那么上面的3条记录都是允许的,因为没有两列主键组合起来是相同的。
没有必要的情况下,我们尽量不使用联合主键,因为它给关系表带来了复杂度的上升。
Summary
- 主键是关系表中记录的唯一标识
- 主键的选取非常重要:主键不要带有业务含义,而应该使用 BIGINT 自增或者 GUID 类型
- 主键也不应该允许使用
NULL - 可以使用多个列作为联合主键,但是不常用
外键
使用主键(ID)作为唯一标识记录时,可以在students表中确定任何一个学生的记录,也可以在classes表中确定任何一个班级的记录
但是,此时我们也会迎来一个问题:如何确定students表的一条记录,例如,id=1的小明,属于哪个班级呢?
班级表和学生表的关系为:“一对多”,为了表达这种关系,需要在students表中加入一列class_id,让它的值与classes表的某条记录相对应,例如:
| id | class_id | name | other columns… |
|---|---|---|---|
| 1 | 1 | 小明 | … |
| 2 | 1 | 小红 | … |
| 5 | 2 | 小白 | … |
这样就可以根据class_id这个列直接定位出一个students表的记录应该对应到classes的哪条记录,例如:
- 小明的
class_id是1,因此,对应的classes表的记录是id=1的一班; - 小红的
class_id是1,因此,对应的classes表的记录是id=1的一班; - 小白的
class_id是2,因此,对应的classes表的记录是id=2的二班。
这也就是外键的概念,在students表中,通过class_id的字段,可以把数据与另一张表关联起来。
外键并不是通过列名实现的,而是通过定义外键约束实现的:
ALTER TABLE studentsADD CONSTRAINT fk_class_idFOREIGN KEY (class_id)REFERENCES classes (id);
其中
- 外键约束的名称
fk_class_id可以任意 FOREIGN KEY(class_id)指定了class_id作为外键REFERENCES classes(id)指定了这个外键将关联到classes表的id列中
优缺点
- 优点:通过定义外键约束,关系数据库可以保证无法插入无效的数据。即如果
classes表不存在id=99的记录,students表就无法插入class_id=99的记录。 - 缺点:降低性能,大部分互联网应用程序为了追求速度,并不设置外键约束,而是仅靠应用程序自身来保证逻辑的正确性。这种情况下,
class_id仅仅是一个普通的列,只是它起到了外键的作用而已。
要删除一个外键约束,也是通过ALTER TABLE实现的:
ALTER TABLE studentsDROP FOREIGN KEY fk_class_id;
△ :删除外键约束并没有删除外键这一列。删除列是通过
DROP COLUMN……实现的
多对多
通过一个表的外键关联到另一个表,我们可以定义出一对多关系。有些时候,还需要定义“多对多”关系。例如,一个老师可以对应多个班级,一个班级也可以对应多个老师,因此,班级表和老师表存在多对多关系。
多对多关系实际上是通过两个一对多关系实现的,即通过一个中间表,关联两个一对多关系,就形成了多对多关系:
教师表:
| id | name |
|---|---|
| 1 | 张老师 |
| 2 | 王老师 |
| 3 | 李老师 |
| 4 | 赵老师 |
班级表:
| id | name |
|---|---|
| 1 | 一班 |
| 2 | 二班 |
中间表关联两个一对多的关系:
| d | teacher_id | class_id |
|---|---|---|
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 1 |
| 4 | 2 | 2 |
| 5 | 3 | 1 |
| 6 | 4 | 2 |
一对一
一对一关系:一个表的记录对应到另一个表的唯一一个记录
例如,students表的每个学生可以有自己的联系方式,如果把联系方式存入另一个表contacts,我们就可以得到一个“一对一”关系
一对一表存在的意义在于把大的表格分为两个较小的表格,目的是把经常读取和不经常读取的字段分开,以获得更高的性能。例如,把一个大的用户表分拆为用户基本信息表user_info和用户详细信息表user_profiles,大部分时候,只需要查询user_info表,并不需要查询user_profiles表,这样就提高了查询速度。
Summary
关系数据库可以通过外键来实现
- 一对多
- 多对多
- 一对一
- 外键既可以通过数据库来约束,也可以不设置约束,仅依靠应用程序的逻辑来保证
索引
索引的意义
- 想要获得非常快的查询速度,就需要使用索引
- 索引是关系数据库中对某一列或多个列的值进行预排序的数据结构
- 不必扫描全表,直接定位到符合条件的记录
例如,对于students表:
| id | class_id | name | gender | score |
|---|---|---|---|---|
| 1 | 1 | 小明 | M | 90 |
| 2 | 1 | 小红 | F | 95 |
| 3 | 1 | 小军 | M | 88 |
如果要经常根据score列进行查询,就可以对score列创建索引:
ALTER TABLE studentsADD INDEX idx_score(score);
使用ADD INDEX idx_score (score)就创建了一个名称为idx_score,使用列score的索引。索引名称是任意的,索引如果有多列,可以在括号里依次写上,例如:
ALTER TABLE studentsADD INDEX idx_name_score(name,score)l
索引的效率取决于索引列的值是否散列,即该列的值如果越互不相同,那么索引效率越高。反过来,如果记录的列存在大量相同的值,例如gender列,大约一半的记录值是M,另一半是F,因此,对该列创建索引就没有意义。
优缺点
- 优点:提高了查询的效率
- 缺点:在插入、更新和删除记录时,需要同时修改索引,因此,索引越多,插入、更新和删除记录的速度就越慢
- 对于主键,关系数据库会自动对其创建主键索引。使用主键索引的效率是最高的,因为主键会保证绝对唯一。
唯一索引
在设计关系数据表的时候,看上去唯一的列,例如身份证号、邮箱地址等,因为他们具有业务含义,因此不宜作为主键。但是,这些列根据业务要求,又具有唯一性约束:即不能出现两条记录存储了同一个身份证号。这个时候,就可以给该列添加一个唯一索引。例如,我们假设students表的name不能重复:
ALTER TABLE studentsADD UNIQUE INDEX uni_name(name);
通过UNIQE关键字,就添加了一个唯一索引,也可以只对某一列添加一个唯一约束而不是创建唯一索引:
ALTER TABLE studentsADD CONSTRAINT uni_name UNIQUE(name);
这种情况下,name列没有索引,但仍然具有唯一性保证。
△ 无论是否创建索引,对于用户和应用程序来说,使用关系数据库不会有任何区别。这里的意思是说,当我们在数据库中查询时,如果有相应的索引可用,数据库系统就会自动使用索引来提高查询效率,如果没有索引,查询也能正常执行,只是速度会变慢。因此,索引可以在使用数据库的过程中逐步优化。
Summary
- 通过对数据库创建索引,可以提高查询速度
- 通过创建唯一索引,可以保证某一列的值具有唯一性
- 数据库索引对于用户和应用程序来说是透明的
查询数据
在导入数据的时候,自己出了一点问题,直接复制使用廖雪峰的教程中的语句,无法进入数据库操作的界面,即直接使用以下语句
mysql -u root -p < init-test-data.sql
从网上查阅导入导出 .sql 文件
参考:linux命令行下导出导入.sql文件
导入数据库
- 首先建立数据库
mysql>create database test;
- 导入数据库
方法一:
mysql> use test;mysql>set names utf8;mysql> source /home/.../init-test-data.sql
方法二:
mysql -u用户名 -p密码 数据库名 < 数据库名.sqlmysql -u root -p test < init-test-data.sql
基本查询
- 查询数据库表的数据
SELECT *FROM <name>
使用SELECT * FROM students时
SELECT是关键字,表示将要执行一个查询*表示“所有列”FROM表示将要从哪个表查询,本例中是students表。
该SQL将查询出students表的所有数据。注意:查询结果也是一个二维表,它包含列名和每一行的数据。
- 判断当前到数据库的连接是否有效
SELECT 1;
虽然SELECT可以用作计算,比如SELECT 100+200,但它并不是SQL的强项。但是,不带FROM子句的SELECT语句有一个有用的用途,就是用来判断当前到数据库的连接是否有效。许多检测工具会执行一条SELECT 1;来测试数据库连接。
Summary
SELECT *FROM <name>可以查询一个表的所有行和所有列- SELECT 查询的结果是一个二维表
条件查询
基本语法
SELECT * FROM <表名> WHERE <条件表达式>
例如
SELECT * FROM students WHERE score >= 80;
三种可以满足的逻辑关系
- 且:
<条件1> AND <条件2>,例如SELECT * FROM students WHERE score >= 80 AND gender = 'M'; - 或:
<条件1> OR <条件2>,例如SELECT * FROM students WHERE score >= 80 OR gender = 'M'; - 非:
NOT <条件>,例如SELECT * FROM students WHERE NOT class_id = 2;,上述NOT条件NOT class_id = 2其实等价于class_id <> 2
常用的条件表达式
| 条件 | 表达式举例1 | 表达式举例2 | 说明 |
|---|---|---|---|
| 使用=判断相等 | score = 80 | name = ‘abc’ | 字符串需要用单引号括起来 |
| 使用>判断大于 | score > 80 | name > ‘abc’ | 字符串比较根据ASCII码,中文字符比较根据数据库设置 |
| 使用>=判断大于或相等 | score >= 80 | name >= ‘abc’ | |
| 使用<判断小于 | score < 80 | name <= ‘abc’ | |
| 使用<=判断小于或相等 | score <= 80 | name <= ‘abc’ | |
| 使用<>判断不相等 | score <> 80 | name <> ‘abc’ | |
| 使用LIKE判断相似 | name LIKE ‘ab%’ | name LIKE ‘%bc%’ | %表示任意字符,例如’ab%’将匹配’ab’,’abc’,’abcd’ |
