数据库:MYSQL基础(SQL注入学习第一步)

1 #一个数据库的建立

1.1 表、库的创建

MYSQL中库的创建很简单:

CREATE DATABASE 数据库名;

表的创建类似,不过要指定其中字段的内容:

CREATE TABLE 表名(
字段名1	数据类型	约束类型,
字段名2	数据类型	约束类型,
......
);

在创建表之前需要先选中数据库,语法是 USE 数据库名

数据库中一般不区分大小写,不过为了方便辨别关键字与参数,我们一般将保留字进行大写,数据进行小写。

1.2 约束:

SQL中的约束

在数据库中,如果存在属性完全相同的两条数据,Mysql就会认为他们是一个实体。为了更好的区分他们,就要引入新的属性。

在 MySQL 中,通常有这几种约束:

约束类型:主键默认值唯一外键非空
关键字:PRIMARY KEYDEFAULTUNIQUEFOREIGN KEYNOT NULL

主键(PRIMARY KEY)作为数据表中一行数据的唯一标识符,在一张表中通过主键就能准确定位到某一行数据,因此主键十分重要,它不能有重复记录且不能为空。

默认值约束 (DEFAULT) 规定,当有 DEFAULT 约束的列,插入数据为空时,将使用默认值。

默认值常用于一些可有可无的字段,比如用户的个性签名,如果用户没有设置,系统给他应该设定一个默认的文本,比如空文本或 ‘这个人太懒了,没有留下任何信息’。

默认值约束 (DEFAULT)只作用于INSERT插入的数据。INSERT语句中,如果被DEFAULT约束的位置没有值,那么会自动填充默认值(若无约束则为NULL)。

唯一约束 (UNIQUE) 比较简单,它规定一张表中指定的一列的值必须不能有重复值,即这一列每个值都是唯一的。当 INSERT 语句新插入的数据和已有数据重复的时候,如果有 UNIQUE 约束,则 INSERT 失败。

外键 (FOREIGN KEY) 既能确保数据完整性,也能表现表之间的关系。

比如,现在有用户表和文章表,给文章表中添加一个指向用户 id 的外键,表示这篇文章所属的用户 id,外键将确保这个外键指向的记录是存在的,如果你尝试删除一个用户,而这个用户还有文章存在于数据库中,那么操作将无法完成并报错。因为你删除了该用户过后,他发布的文章都没有所属用户了,而这样的情况是不被允许的。同理,你在创建一篇文章的时候也不能为它指定一个不存在的用户 id。

一个表可以有多个外键,每个外键必须 REFERENCES (参考) 另一个表的主键,被外键约束的列,取值必须在它参考的列中有对应值。

非空约束 (NOT NULL),听名字就能理解,被非空约束的列,在插入值时必须非空。

如何定义约束?

在创建表的时候有两种方式对字段进行约束:

EXP1:	直接创建约束
CREATE TABLE users
(
	id INT(10) PRIMARY KEY,
	name CHAR(20),
)
;

EXP2:	建表的同时命名PRIMARY KEY约束,并定义多个列的PRIMARY KEY约束(推荐使用)
CREATE TABLE users
(
	id INT(10) NOT NULL,
	name CHAR(20),
	phone INT(13)	DEFAULT	10086,
	CONSTRAINT pk_UsersId PRIMARY KEY (name,phone);
)
;

Q:为什么推荐使用第二种方式进行约束?约束命名的好处是什么?

A:当你使用第一种方式对字段进行约束的时候,约束也会被命名,不过是服务自动为其命名,具有很强的随机性。当你的SQL语句因约束问题出错时,ERROR信息中会回显出约束的名称。试想当你试图解决问题时,看到报错信息中一长串的随机值而无从下手,那时候你就会后悔没有对你定义的约束进行合理的命名了。此外,如果某天你的MANAGER想要让你修改一些字段的约束,如果你不知道它的名称,很难做到,尤其是对一些外键约束,你会为了搞清楚字段间的关系而殚精竭虑的。

练习:

搭建一个简易的成绩管理系统的数据库
介绍

现需要构建一个简易的成绩管理系统的数据库,来记录几门课程的学生成绩。数据库中有三张表分别用于记录学生信息、课程信息和成绩信息。

数据表结构如下:

学生表(student):学生 id 、学生姓名和性别

此处输入图片的描述

课程表:课程 id 和课程名

此处输入图片的描述

成绩表:成绩 id 、学生 id 、课程 id 和分数

此处输入图片的描述

服务器中的 MySQL 还没有启动,请注意 MySQL 的 root 账户默认密码为空。

目标

1.MySQL 服务处于运行状态

2.新建数据库的名称为 gradesystem

3.gradesystem 包含三个表:student、course、mark;

  • student 表包含 3 列:sid(主键)、sname、gender;

  • course 表包含 2 列:cid(主键)、cname;

  • mark 表包含 4 列:mid(主键)、sid、cid、score ,注意与其他两个表主键之间的关系。

    4.将上述表中的数据分别插入到各个表中

提示
  • 建立表时注意 id 自增和键约束
  • 每个表插入语句可通过一条语句完成
实现代码
sudo service mysql start

mysql -u root
CREATE DATABASE gradesystem;

use gradesystem

CREATE TABLE student(
    sid int NOT NULL AUTO_INCREMENT,
    sname varchar(20) NOT NULL,
    gender varchar(10) NOT NULL,
    PRIMARY KEY(sid)
    );

CREATE TABLE course(
    cid int NOT NULL AUTO_INCREMENT,
    cname varchar(20) NOT NULL,
    PRIMARY KEY(cid)
    );

CREATE TABLE mark(
    mid int NOT NULL AUTO_INCREMENT,
    sid int NOT NULL,
    cid int NOT NULL,
    score int NOT NULL,
    PRIMARY KEY(mid),
    FOREIGN KEY(sid) REFERENCES student(sid),
    FOREIGN KEY(cid) REFERENCES course(cid)
    );

INSERT INTO student VALUES(1,'Tom','male'),(2,'Jack','male'),(3,'Rose','female');

INSERT INTO course VALUES(1,'math'),(2,'physics'),(3,'chemistry');

INSERT INTO mark VALUES(1,1,1,80),(2,2,1,85),(3,3,1,90),(4,1,2,60),(5,2,2,90),(6,3,2,75),(7,1,3,95),(8,2,3,75),(9,3,3,85);

2 #数据查询语言

掌握的内容:

  • 基本语法
  • 数学符号条件
  • AND OR IN
  • 模糊查询
  • 对查询结果排序
  • SQL 内置函数和计算
  • 子查询与连接查询

样库内容:

三张表,每张表内容如下:

项目表

image-20220725212034150

雇员表

image-20220725212041605

部门表

image-20220725212048555

2.1 SELECT

SELECT 要查询的列名 FROM 表名 WHERE 限制条件 ORDER BY 要排序的字段名;

关键字 LIKE 可用于实现模糊查询,常见于搜索的限制条件中。和 LIKE 联用的通常还有通配符,代表未知字符。SQL 中的通配符是 _% 。其中 _ 代表一个未指定字符,% 代表不定个未指定字符。

查询雇员表中电话号码前四位为1101且号码长度为6位的雇员信息
SELECT name,age,phone FROM employee WHERE phone LIKE '1101__';
--------------------------------------------------------------
查询雇员表中雇员姓名以J字母打头的雇员信息
SELECT name,age,phone FROM employee WHERE name LIKE 'J%';

关键词 ORDER BY有两个选项,DESC(降序排序) ASC(升序排序)。如果不加选项将默认升序排序。

查询雇员表中雇员的信息,按工资降序排列
SELECT name,age,salary,phone FROM employee ORDER BY salary DESC;

SQL内置的和运算函数有五种:

函数名:COUNTSUMAVGMAXMIN
作用:计数求和求平均值最大值最小值
查询雇员表中工资最高与最低的雇员工资,并分别以max_salary、min_salary展现出来
SELECT MAX(salary) AS max_salary,MIN(salary) AS min_salary FROM employee;

12

子查询:

上面讨论的 SELECT 语句都仅涉及一个表中的数据,然而有时必须处理多个表才能获得所需的信息。这时可以使用子查询

查询Tom雇员所在项目的项目名称及该项目的个数
SELECT of_dpt,COUNT(proj_name) AS count_project FROM project GROUP BY of_dpt
HAVING of_dpt IN
(SELECT in_dpt FROM employee WHERE name='Tom');

--------------------------------------------------------------------------------
上面代码包含两个 SELECT 语句,第二个 SELECT 语句将返回一个集合的数据形式,然后被第一个 SELECT 语句用 in 进行判断。

HAVING 关键字可以的作用和 WHERE 是一样的,都是说明接下来要进行条件筛选操作。

区别在于 HAVING 用于对分组后的数据进行筛选

子查询可以嵌套3层、4......

两个查询语句的结果:

image-20220725210238870

最终构造的查询语句结果:

image-20220725210404332

连接查询:

在处理多个表时,子查询只有在结果来自一个表时才有用。但如果需要显示两个表或多个表中的数据,这时就必须使用连接 (join) 操作。 连接的基本思想是把两个或多个表当作一个新的表来操作

查询各员工所在部门的人数
SELECT id,name,people_num
FROM employee,department
WHERE employee.in_dpt = department.dpt_name
ORDER BY id;
------------------------------------------------------
另一个连接语句格式是使用 JOIN ON 语法,刚才的语句等同于:
SELECT id,name,people_num
FROM employee JOIN department
ON employee.in_dpt = department.dpt_name
ORDER BY id;

执行结果:

14

练习:

使用连接查询的方式,查询出各员工所在部门的人数与工程数,工程数命名为 count_project。(连接 3 个表,并使用 COUNT 内置函数)

SELECT name, people_num, COUNT(proj_name) AS count_project
  FROM employee, department, project
  WHERE in_dpt = dpt_name AND of_dpt = dpt_name
  GROUP BY name, people_num;

3 #数据库及表的删除与修改

3.1 删除数据库:

DROP DATABASE 库名;

关于修改数据库:

目前 Mysql 没有提供修改数据库名称的方法,因为这曾导致一系列安全问题。

在老版本中 RENAME DATABASE 可以修改数据库名称,这条命令在 MySQL 5.1.7 中被加入,但官方很快就发现这条命令所带来的危险,于是在 MySQL 5.1.23 中把这条命令移除。

事实上,数据库名几乎不会遇到必须修改的情况,如果你一定要这么做,比较安全的做法是重新建一个新库,然后将旧库中的数据转移到新库中,并且暂时不要删除旧的数据库,以防数据遗失。

3.2 对一张表的修改

修改表名:

RENAME TABLE 原名 TO 新名字;

ALTER TABLE 原名 RENAME 新名;

ALTER TABLE 原名 RENAME TO 新名;

删除一张表:

DROP TABLE 表名字;

3.3 对表结构的修改(对一列的修改)

增加一列:

ALTER TABLE 表名字 ADD COLUMN 列名字 数据类型 约束;
或:
ALTER TABLE 表名字 ADD 列名字 数据类型 约束;

新增加的一列会被默认放置到该表的最右边。如果要将列插入到指定的位置,要使用AFTER修饰。

如果要将新插入的字段插入第一列,要使用FIRST修饰。

现在 employee 表中有 id、name、age、salary、phone、in_dpt 这 6 个列,我们尝试加入 height (身高)一个列并指定 DEFAULT 约束:
ALTER TABLE employee ADD height INT(4) DEFAULT 170;
-------------------------------------------------------------------------------------------------------------
现在,在age属性前加入weight字段,并指定DEFAULT约束:
ALTER TABLE employee ADD weight INT(4) DEFAULT 120 AFTER age;
---------------------------------------------------------------
在该表最左侧新加一个名为test的字段:
ALTER TABLE employee ADD test INT(4) DEFAULT 666 FIRST;

操作后的employee表:

image-20220725223345638

删除一列:

删除表中的一列和刚才使用的新增一列的语句格式十分相似,只是把关键词 ADD 改为 DROP ,语句后面不需要有数据类型、约束或位置信息。具体语句格式:

ALTER TABLE 表名字 DROP COLUMN 列名字;

或: ALTER TABLE 表名字 DROP 列名字;

我们把刚才新增的 test 删除:

ALTER TABLE employee DROP test;

重命名一列:

这条语句其实不只可用于重命名一列,准确地说,它是对一个列做修改(CHANGE)

ALTER TABLE 表名字 CHANGE 原列名 新列名 数据类型 约束;

注意:这条重命名语句后面的 “数据类型” 不能省略,否则重命名失败。

原列名新列名相同的时候,指定新的数据类型约束,就可以用于修改数据类型或约束。需要注意的是,修改数据类型可能会导致数据丢失,所以要慎重使用。

用这条语句将 “height” 一列重命名为汉语拼音 “shengao” ,效果如下:

ALTER TABLE employee CHANGE height shengao INT(4) DEFAULT 170;

执行结果:

image-20220725224437526

改变数据类型:

要修改一列的数据类型,除了使用刚才的 CHANGE 语句外,还可以用这样的 MODIFY 语句:

ALTER TABLE 表名字 MODIFY 列名字 新数据类型;

再次提醒,修改数据类型必须小心,因为这可能会导致数据丢失。在尝试修改数据类型之前,请慎重考虑。

3.4 对表内容的修改:

修改表中的某个值:

大多数时候我们需要做修改的不会是整个数据库或整张表,而是表中的某一个或几个数据,这就需要我们用下面这条命令达到精确的修改:

UPDATE 表名字 SET1=1,2=2 WHERE 条件;

比如,我们要把 Tom 的 age 改为 21,salary 改为 3000:

UPDATE employee SET age=21,salary=3000 WHERE name='Tom';

执行结果:

image-20220725224907726

注意:一定要有WHERE条件,不然语句会作用表内所有的数据。

不使用WHERE约束条件进行UPDATE操作:
UPDATE employee SET age=22;

执行结果

image-20220725225701396

删除一行数据:

删除表中的一行数据,也必须加上 WHERE 条件,否则整列的数据都会被删除。删除语句:

DELETE FROM 表名字 WHERE 条件;

我们尝试把 Tom 的数据删除:

DELETE FROM employee WHERE name='Tom';

执行结果:

image-20220725225049950

4 其他基本操作

  • 索引:可以加快查询速度
  • 视图:是一种虚拟存在的表
  • 导入:从文件中导入数据到表
  • 导出:从表中导出到文件中
  • 备份:mysqldump 备份数据库到文件
  • 恢复:从文件恢复数据库

4.1 索引

索引是一种与表有关的结构,它的作用相当于书的目录,可以根据目录中的页码快速找到所需的内容。

当表中有大量记录时,若要对表进行查询,没有索引的情况是全表搜索:将所有记录一一取出,和查询条件进行对比,然后返回满足条件的记录。这样做会执行大量磁盘 I/O 操作,并花费大量数据库系统时间。

而如果在表中已建立索引,在索引中找到符合查询条件的索引值,通过索引值就可以快速找到表中的数据,可以大大加快查询速度

对一张表中的某个列建立索引,有以下两种语句格式:

ALTER TABLE 表名字 ADD INDEX 索引名 (列名);

CREATE INDEX 索引名 ON 表名字 (列名);

索引的效果是加快查询速度,当表中数据不够多的时候是感受不出它的效果的。

使用SHOW INDEX FROM 表名字;查看索引。

在使用 SELECT 语句查询的时候,语句中 WHERE 里面的条件,会自动判断有没有可用的索引

比如有一个用户表,它拥有用户名(username)和个人签名(note)两个字段。其中用户名具有唯一性,并且格式具有较强的限制,我们给用户名加上一个唯一索引;个性签名格式多变,而且允许不同用户使用重复的签名,不加任何索引。

这时候,如果你要查找某一用户,使用语句 select * from user where username=?select * from user where note=? 性能是有很大差距的,对建立了索引的用户名进行条件查询会比没有索引的个性签名条件查询快几倍,在数据量大的时候,这个差距只会更大。

一些字段不适合创建索引,比如性别,这个字段存在大量的重复记录无法享受索引带来的速度加成,甚至会拖累数据库,导致数据冗余和额外的 CPU 开销。

4.2 视图

视图是从一个或多个表中导出来的表,是一种虚拟存在的表。它就像一个窗口,通过这个窗口可以看到系统专门提供的数据,这样,用户可以不用看到整个数据库中的数据,而只关心对自己有用的数据。

注意理解视图是虚拟的表:

  • 数据库中只存放了视图的定义,而没有存放视图中的数据,这些数据存放在原来的表中;
  • 使用视图查询数据时,数据库系统会从原来的表中取出对应的数据;
  • 视图中的数据依赖于原来表中的数据,一旦表中数据发生改变,显示在视图中的数据也会发生改变;
  • 在使用视图的时候,可以把它当作一张表。

创建视图的语句格式为:

CREATE VIEW 视图名(列a,列b,列c) AS SELECT1,2,3 FROM 表名字;

可见创建视图的语句,后半句是一个 SELECT 查询语句,所以视图也可以建立在多张表上,只需在 SELECT 语句中使用子查询连接查询,这些在之前的实验已经进行过。

练习:

现在我们创建一个简单的视图,名为 v_emp,包含v_namev_agev_phone三个列:

建议一个雇员表的视图,其中包括雇员的姓名、年龄和电话号码:
CREATE VIEW v_emp (v_name,v_age,v_phone) AS SELECT name,age,phone FROM employee;

02

对视图的修改就是对基本表的修改,修改视图的内容会将基本表中对应的数据一并修改。

4.3 导入

此处讲解的是导入一个纯数据文件,该文件中将包含与数据表字段相对应的多条数据,这样可以快速导入大量数据,除此之外,还有用 SQL 语句的导入方式,语法为:source *.sql 这是实验中经常用到的。两者之间的不同是:数据文件导入方式只包含数据,导入规则由数据库系统完成;SQL 文件导入相当于执行该文件中包含的 SQL 语句,可以实现多种操作,包括删除,更新,新增,甚至对数据库的重建。

数据文件导入,可以把一个文件里的数据保存进一张表。导入语句格式为:

LOAD DATA INFILE '文件路径和文件名' INTO TABLE 表名字;
练习:

现在桌面上有一个名为 in.txt 的文件,我们尝试把这个文件中的数据导入数据库 mysql_shiyanemployee 表中。

由于导入导出大量数据都属于敏感操作,根据 mysql 的安全策略,导入导出的文件都必须在指定的路径下进行,在 mysql 终端中查看路径变量:

mysql -uroot
mysql> show variables like '%secure%';
+--------------------------+-----------------------+
| Variable_name            | Value                 |
+--------------------------+-----------------------+
| require_secure_transport | OFF                   |
| secure_auth              | ON                    |
| secure_file_priv         | /var/lib/mysql-files/ |
+--------------------------+-----------------------+
3 rows in set (0.00 sec)

注意到 secure_file_priv 变量指定安全路径为 /var/lib/mysql-files/ ,要导入数据文件,需要将该文件移动到安全路径下。

打开 Xfce 终端,输入命令拷贝 in.txt 文件夹到 /var/lib/mysql-files/ 目录:

sudo cp -a /home/shiyanlou/Desktop/in.txt /var/lib/mysql-files/

使用命令 sudo cat /var/lib/mysql-files/in.txt 查看 in.txt 文件中的内容:

image-20220726104913365

可以看到其中仅仅包含了数据本身,没有任何的 SQL 语句

下面我们将in.txt中的数据添加到employee表中:

先查看未更新前的表:

image-20220726105142755

现在执行语句,将数据导入该表:

LOAD DATA INFILE '/var/lib/mysql-files/in.txt' INTO TABLE employee;

查询插入后的表内容如下:

image-20220726105431766

4.4 导出

导出与导入是相反的过程,是把数据库某个表中的数据保存到一个文件之中。导出语句基本格式为:

SELECT1,列2 INTO OUTFILE '文件路径和文件名' FROM 表名字;

注意:语句中 “文件路径” 之下不能已经有同名文件。

练习:

现在我们把整个 employee 表的数据导出到 /var/lib/mysql-files/ 目录下,导出文件命名为 out.txt 具体语句为:

SELECT * INTO OUTFILE '/var/lib/mysql-files/out.txt' FROM employee;

查看out.txt结果如下:

sudo cat /var/lib/mysql-files/out.txt

image-20220726110117357

4.5 备份

数据库中的数据十分重要,出于安全性考虑,在数据库的使用中,应该注意使用备份功能。

备份与导出的区别:导出的文件只是保存数据库中的数据;而备份,则是把数据库的结构,包括数据、约束、索引、视图等全部另存为一个文件。

mysqldump 是 MySQL 用于备份数据库的实用程序。它主要产生一个 SQL 脚本文件,其中包含从头重新创建数据库所必需的命令 CREATE TABLE INSERT 等。

使用 mysqldump 备份的语句:

mysqldump -u root 数据库名>备份文件名;   #备份整个数据库

mysqldump -u root 数据库名 表名字>备份文件名;  #备份整个表

mysqldump 是一个备份工具,因此该命令是在终端中执行的,而不是在 mysql 交互环境下

练习:

我们尝试备份整个数据库 mysql_shiyan,将备份文件命名为 bak.sql

cd /home/shiyanlou/
mysqldump -uroot mysql_shiyan > bak.sql

执行结束后查看结果:

image-20220726110751320

ls查看当前路径下的文件,可以发现已经存在bak.sql。

尝试查看该文件内容:

image-20220726111101621

可以看到内部存储了系统自动生成的sql语句,包括建表、插入数据等等。。。

4.6 恢复

用备份文件恢复数据库的方式也很简单:

SOURCE 备份文件路径
OR
mysql -uroot 要恢复的数据库名 < 备份文件
练习:

我们使用第二种方式恢复数据库:

先创建一个载体数据库:
CREATE DATABASE test;	//MYSQL命令行
恢复数据库到test中:
mysql -uroot test < bak.sql	//终端执行	

查看test数据库内容:

image-20220726112152432

恢复成功。

再查看employee表内容:

image-20220726112246494

视图练习:

建立员工名字 employee.name 和对应部门人数 department.people_num 的视图并展示。

以下内容仅供参考,为了能有更好的学习效果,请尽量按自己的想法来完成练习题。

CREATE VIEW name_people_num (name, people_num)
  AS SELECT name, people_num FROM employee, department
  WHERE in_dpt = dpt_name;
SELECT * FROM name_people_num;
+------+------------+
| name | people_num |
+------+------------+
| Alex |         11 |
| Ken  |         11 |
| Mike |         11 |
| Jack |         12 |
| Jobs |         12 |
| Joe  |         12 |
| Mary |         12 |
| Tony |         10 |
| Rose |         10 |
| Rick |         10 |
| Tom  |         15 |
| Jim  |         15 |
+------+------------+
12 rows in set (0.00 sec)

再查看employee表内容:

[外链图片转存中…(img-wCDJc9oe-1658808012017)]

视图练习:

建立员工名字 employee.name 和对应部门人数 department.people_num 的视图并展示。

以下内容仅供参考,为了能有更好的学习效果,请尽量按自己的想法来完成练习题。

CREATE VIEW name_people_num (name, people_num)
  AS SELECT name, people_num FROM employee, department
  WHERE in_dpt = dpt_name;
SELECT * FROM name_people_num;
+------+------------+
| name | people_num |
+------+------------+
| Alex |         11 |
| Ken  |         11 |
| Mike |         11 |
| Jack |         12 |
| Jobs |         12 |
| Joe  |         12 |
| Mary |         12 |
| Tony |         10 |
| Rose |         10 |
| Rick |         10 |
| Tom  |         15 |
| Jim  |         15 |
+------+------------+
12 rows in set (0.00 sec)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值