MySQL数据库基础(1)--基础知识与简单操作

一、数据库基础知识

数据库Database,是一种特殊的电子型存储文件,以特殊的方式将数据存储起来,其可以做到①持久化存储②读写速度极高③保证数据的有效性④支持各种程序/操作系统,与普通文件存储相比,其速度快、效率高,且同时可以保存数据关系等内容和对数据进行批量操作,尤其是在极大量数据处理时拥有无可比拟的优势,应用面极广。

关系型数据库与非关系型数据库
主流的关系型数据库有Oracle, MySQL等,非关系型数据库有Mongodb, Redis等,关系型数据库是建立在关系模型(二维表格模型)基础上的数据库,即由二维表及其之间的联系组成的一个数据组织,非关系型数据库严格意义上不是一种数据库,而是一种数据结构化存储方法的集合。
(1)关系型数据库的优缺点:易于维护,使用方便,可以复杂操作,有事务处理(可以保持数据的一致性,安全性能高),海量数据读写性能较差,表结构固定,高并发读写需求;
(2)非关系型数据库的优缺点:格式灵活,速度快,高扩展性,低成本,不提供sql服务(学习使用成本高),数据结构复杂,无事务处理。其一般有文档型/键值对型/列式/图形。
:①关于常见的关系型和非关系型数据库及其对比在前文中有较详细介绍;
②在实际运用中,一般使用非关系型数据库来做缓存、临时存储等,海量数据的持久性存储一般都使用关系型数据库存储。

RDBMS:Relational Database Management System关系型数据库管理系统,是一套程序接口,用于操作关系型数据库中的数据,其设计为CS模式。
SQL:Structured Query Language结构化查询语言,其是一种专用于操作关系型数据库的语言,所有的关系型数据库都支持SQL,其下分为:

DQL:Data Query Language数据查询语言,用于对数据进行查询,如select
DML:Data Manipulation Language数据操作语言,对数据进行增加、修改、删除,如insert、udpate、delete
TPL:Transaction Processing Language事务处理语言,对事务进行处理,包括begin transaction、commit、rollback
DCL:Data Control Language数据控制语言,进行授权与权限回收,如grant、revoke
DDL:Data Definition Language数据定义语言,进行数据库、表的管理等,如create、drop
CCL:指针控制语言,通过控制指针完成表的操作,如declare cursor

DB-API:Database Application Programming Interface标准数据库应用编程接口,是python提供的用于与数据库驱动程序交互的工具,MySQL-Connector/Python是第三方提供的用于与底层数据库交互和与DB-API交互的模块(其与pymysql都是python模块),即从代码到数据库中间隔了两个技术层(DB-API,驱动)。

使用DB-API连接到MySQL的步骤
(1)以mysql-connector为例
①定义连接属性(需要四部分信息Ⅰ运行MySQL服务器的计算机的IP地址/主机名,Ⅱ要使用的用户ID,Ⅲ与用户ID关联的口令,Ⅳ这个用户ID想要交互的数据库名),驱动程序允许将这些连接属性放在一个字典中,便于使用和引用;
②导入数据库驱动程序,在python中是import mysql.connector
③建立与服务器的连接,其是一个对象,一般用一个变量保存,conn = mysql.connector.connect(**dbconfig),其中dbconfig是①中建立的定义连接属性的字典;
④创建一个游标,cursor = conn.cursor()
⑤执行查询;
⑥关闭游标和连接,cursor.close(), conn.close()

使用游标执行查询的步骤:一般将SQL语句(字符串)赋值给变量_SQL,然后使用游标操作cursor.execute(_SQL),可以执行SQL语句,请求结果的游标方法有多个:
cursor.fetchone()用于获取一行结果;
cursor.fetchmany()用于获取指定的任意行结果;
cursor.fetchall()用于获取结果中的所有数据行);
为了避免硬编码数据(将所有数据值详细输入),python的DB-API允许在SQL串中放置占位符,_SQL = ‘insert into log (phrase, letters, ip, browser_string, results) values (%s, %s, %s, %s, %s)’ 然后在调用游标时 cursor.execute(_SQL, (‘a’, ‘b’, ‘c’, ‘d’, ‘e’))再用一个元组输入值(即字符串的格式化),由于写入数据库开销很大,所以很多数据库会将insert语句缓存,之后一次性应用全部,可以使用conn.commit()方法强制数据库系统将所有缓存的数据全部提交到数据库表中。
:上述为较底层的调用方法,在实际运用时一般采用ORM(Django)或SQL alchemy,其是一类将操作数据库封装为类对象操作的模块,在前文(元类相关)中描述过其原理,主要目的是减小开发者负担及避免SQL注入等安全问题。

使用pymysql操作数据库
①创建connect对象,连接数据库 conn = connect(host, port, database, user, password, charset),注意必须使用关键字参数传入,不能使用字典和元组,在mysql.connector中可以利用字典传入,conn.close()关闭连接,conn.commit()刷新提交(不执行时会提交请求,如auto_increment会递增,但是不会执行,这是为了保证多任务时不出错),conn.cursor()创建游标对象,conn.rollback()回滚(用于commit之前撤销);
②创建cursor对象,cursor = conn.cursor()cursor.execute(SQL)执行语句,并返回受影响的行数(返回值是个整数,而受影响的行数据保存),cursor.close()关闭,cursor.fetchall/one/many(),分别返回全部/单行/多行(在括号中指定行数,返回嵌套元组),注意fetchall等方法采用迭代器模式,取过的行不能再取;
③游标与连接对象关闭。

数据库中的一些关键字:每一行称为一条记录(record/元组tuple),每一列称为一个字段(field),唯一标识字段的称为主键(primary key),一张表中可以有多个主键。在表中为了更加准确的存储数据,保证数据的正确有效,可以在创建表的时候,为表添加一些强制性的验证,包括数据字段的类型、约束。

数据类型:其原则为在够用的前提下尽可能使用取值范围小的,利于节省空间;
整数(tinyint/smallint/mediumint/int/bigint分别为1/2/3/4/8字节,有正负),
小数(decimal(5,2)表示一共5位有2位小数),
字符串(varchar(表示可变长度的字符串,不会自动补空格,不得超出设置长度如varchar(3))/char(固定长度的字符串,若输入数据不足位则会在后方添加空格补足)/text(存储大文本,当字符大于4000时)),
日期时间(date/time/datetime),
枚举类型(enum将可能的结果列举出来enum(‘x’, ‘y’)),
对于图片视频等文件,其一般不存储在数据库中,在某个服务器上保存,然后在表中以字符串的方式存储这个文件的保存路径。

数据约束:主键primary key(在物理上的存储顺序),非空not null(此字段不允许为空),唯一unique(此字段不允许重复),默认default(当不填写时使用默认值),外键foreign key(如果一个表中一个字段里的值都是另外一个表中的主键,则称这个字段为外键,外键可以约束此字段的数据有效性(检查另外一个表的数据),但是会影响数据库的增删改查性能,一般在逻辑层(即代码)控制)。

数据库的存储引擎:innodb支持外键/事务处理/行级锁,其索引和内容紧密结合,MylSAM不支持但读性能相对高,其索引和内容是分开存储的。

文件及注释:sql后缀的文件为SQL语言文件,在其中–表示注释。

一些指令:在SQL中不区分大小写(一般采用大写),分号表示命令结束,SQL中’-’会被认为分开,使用xxx将内容视为整体。

:数据库操作时会自动转换类型,如写入的以字符串类型表示的数若存储到限定类型为整型的字段中时会自动转为整型,但字符串类型的值必须加引号。

二、SQL语句简介

下述的所有sql语句都以MySQL为准,MySQL的8.x版本已出,其在部分操作和语句上与MySQL5.x有不同,但现在多应用的还是5.x版本。

在已安装MySQL服务器并且保证服务开启后(安装及开启服务网上教程很多),在终端中输入mysql -u 用户名 -p ,之后输入密码即可进入MySQL数据库,在数据库中使用exit/quit指令即可退出数据库,注意在sql语句中,分号表示语句结束。

基础操作
查看数据库show databases;
显示当前时间select now();
显示当前数据库版本select version();
创建数据库 create database dbname charset=utf8; (一般指定编码方式为utf8)
查看数据库创建信息 show create database dbname;
删除数据库 drop database dbname;
查看当前使用的数据库select database(); (若无则返回NULL)
使用数据库 use dbname;
查看当前数据库的所有表 show tables;
创建表(字段与字段之间以逗号隔开,可换行,可以同时存在多个约束并且与顺序无关,int unsigned表示无符号整数,自动输入0/null/default时激活) ,可以在tabname前加上if not exists表示如果不存在则创建

create table tabname(字段 类型 约束, id int primary key auto_increment not null, name varchar(30) default ‘wang’); 

查看一个表的结构 desc tabname;
查看一个表的创建信息 show table create tablename;

修改表结构
添加字段(添加新的一列)alter table tabname add fieldname 类型 约束;
修改字段(不修改原来字段名只修改字段类型/约束)alter table tabname modify fieldname 类型 约束;
修改字段(修改字段名并且修改字段类型/约束,类型必加,同时修改多个时需要以逗号隔开)alter table tabname change oldname newname 类型 约束, change oldname new name 类型 约束;
删除字段(若表中有记录,则该字段数据也会被同时删除) alter table tabname drop fieldname;

数据的增删改查CURD(create,update,read,delete)

(1)插入记录(enum类型中可以按索引插入从1开始,可以同时插入多行)

insert into tabname values(0, 'a', 'b'), (1, 'b', 'a'); (必须将所有字段写全,包括有默认值的字段)
insert into tabname (field2, field4) values (xx1, xx2), (yy1, yy2);
insert into tabname1 (field) select field1 from tabname2 xxx;(从其他表中查询数据并插入该表,注意字段数量需要对应,不用添加values)

(2)修改记录(如无where条件则将表中对应字段全部修改,可以同时修改多个数据,一般以主键为识别手段,不可以设置同时满足多个条件)

update tabname set fieldname1=xx, fieldname3=yy (where filedname5=zz);

(3)查询记录(SQL语句中最重要的部分,后详)

select * from tabname where filedname=xx;(查询满足条件的记录)
select * from tabname; (查询表中所有内容,若数据量巨大,则不适用)
select fieldname1 as ‘姓名’, fieldname2 as ‘性别’ from students where yy;
(此中查询方式会修改返回的表的字段名为设置值,且限定了返回表的字段数量)
select tabname.fieldname from tabname;(另一种选择字段的方法)
select s.fieldname from tabname as s; 还可以给表起别名,起别名之后原名在该语句中不能继续用
select * from students where age>18 and age<28; 查询时可以使用where添加条件(其支持比较运算符和逻辑运算符) 
select distinct filedname from tabname; 字段前可以添加方式,如去重,会只显示不重复的记录,注意若选择多个字段,则只有当每个字段的值都相同时两条记录才会合并显示

(4)删除数据

delete from tabname;(清空数据表)
delete from tabname where fieldname=xx;(删除指定的记录)

:①在实际运用中,一般增添一个is_delete字段bit类型(对应比特位,如2个比特可以存储4个值),使用逻辑删除表示删除,即将不可用的数据的is_delete字段修改为1;
修改和删除都要慎用啊!
③注意区分字段与记录,查询的返回值中字段指的是列,记录指的是行。

数据库的查询

(1)模糊查询(使用like关键字,位于where关键字之中):
①like 后面以%替代0/1/多个字符,以_替代1个字符 select * from students where filedname like ‘%小%’;
②rlike 正则替换,后续例子表示查询以周开头以伦结尾的名字,select * from students where name rlike ‘^周.*伦$’;

(2)范围查询(使用逻辑判断与比较运算符,判断相等为’=‘而非’==’):
①in 表示查询在指定的集合内(非连续),select * from students where age (not) in (12, 18, 34);
②between a and b表示查询在指定的范围内(包括前后值),select * from students where age (not) between 18 and 34;
select * from students where 18 <= age <= 34;等价
③判断空/非空,select * from students where age is (not) null;

(3)排序查询(使用order by关键字,位于where关键字之后):
默认按主键排序,默认排序为asc(从小到大)order by后的字段可以重复,重复时作用机制为首先按第一个字段排序,第一个字段相同时按第二个字段排序,以此类推select * from students where (age between 18 and 38) and gender='男' order by age asc(从小到大) /desc(从大到小), id asc;

(4)聚合函数:
是一组用于统计的函数,select round(count/max/min/sum/avg(*/fieldname), 3) as ‘qqq’ from tabname where xx; 其中round(x, 3)意为保留3位小数,是一种不精确计算(其自动四舍五入),其支持表达式和算术运算符(因为内存中浮点数是不精确的,因此在数据库中一般会存储整数,在使用时再对其进行运算)。
:其中as后为自定义名,查得的内容只有一个字段(即自定义的字段)且只有一条记录。

(5)分组查询:
可以解决聚合函数中无法同时查询多个字段的问题,相当于建立了一个新的表将数据置入,然后分别对新的表里面的数据进行查询,在查询时一般添加分组凭据作为首列 select gender, round(count/max/min/sum/avg(*/fieldname), 3) as ‘qqq’ from tabname where xxx group by gender; 另有方法可以将详细信息显示出来,group_concat(xxx, ''),其中会将以逗号隔开的所有值连接起来显示,因此一般多个字段之间添加标识符,select gender, group_concat(id, '_', name, '_', height) as 'qq' from tabname where age>20 group by gender;注意其中where条件(对结果进行条件判断)可以不使用分组凭据;使用having可以对分组进行条件判断,如果条件达成则显示,否则不显示,select gender, group_concat(name), avg(age) from tabname where height>170 group by gender having count(*)>3; 分组一般与聚合函数一起使用,在group_concat(a, b order by b)内部可以排序。
:①分组查询其实就是构建了一个新表,以分组的字段为基准,将其中的非重复值提出,做成一个只有一个字段的表;
②由于分组查询所得的表只有一个字段,因此其无法选择显示原表中字段(因为在新表中没有),使用having条件可以对分组进行条件判断,如count(*)意为分组后当前组有多少条原表的记录;
③如果想在新表中显示原表其他字段内容,就使用group_concat()其会将括号中的字段连接起来,记录之间以逗号隔开,即相当于是新建了一个字段,这个字段中的值是原表中字段的合并,举例如下;
MySQL数据库基础(1)--基础知识与简单操作_第1张图片
MySQL数据库基础(1)--基础知识与简单操作_第2张图片
④在sql语法中规定聚合函数不能与where关键字连用,因此having常出现于经常使用聚合函数的分组排序中。

(6)分页:
即限制显示数量,可以用limit start, count其中start表示从此条的下一个开始,count表示限制数据数量,limit不支持表达式,放置在语句最后。

(7)链接查询:
即多个表的关联查询(通过外键)
①内链接,select * from tabname1 inner join tabname2表示将表1的内容对表2进行迭代,新表字段会将两个表的字段叠加,产生的记录数为两个表的记录数相乘;
一般使用select t1.fieldname, t2.fieldname from tabname1 as t1 inner join tabname2 as t2 on t1.fieldname5=t2.fieldname1; 表示根据指定的字段条件筛选新表中的数据;
MySQL数据库基础(1)--基础知识与简单操作_第3张图片
②外链接,分为左链接和右链接,left join 意为以左边的表的记录为基准,不匹配的记录依然显示但显示为null,right join类似,以右边的表为基准,但比较少用,一般用左连接完成(将两个表对调顺序)。
MySQL数据库基础(1)--基础知识与简单操作_第4张图片

(8)自关联:一个特殊的表结构,表里面的字段关联同一个表里的另一个字段,如省市区/上下级(同属一个表结构,将一个字段的数据链接到这个表的主键,使用select t1.f1, t2.f1 from tabname as t1 inner join tabname as t2 on t1.f1=t2.f2 having t1.f1 = 'a';即对一个表起两个别名,当作两个表来使用。
:having关键字一般用于新生成的表的条件限制。
在这里插入图片描述

(9)嵌套查询:也叫子查询,例如select * from tabname where fieldname1 = (select max(age) from tabname);即将SQL语句嵌套,其性能比关联查询低。

(10)select语句的语法顺序与执行顺序

SELECT select_expr [,select_expr,...] [      
      FROM tb_name
      [WHERE 条件判断]
      [GROUP BY {col_name | postion} [ASC | DESC], ...] 
      [HAVING 条件判断]
      [ORDER BY {col_name|expr|postion} [ASC | DESC], ...]
      [ LIMIT {[offset,]rowcount | row_count OFFSET offset}]
]

执行顺序为:
①from表名,where对数据筛选
②group by分组
③select选择显示对象,group_concat拼接及排序,distinct去重
④having对分组进行筛选,分组排序
⑤limit限制显示
注:此中没有提及链接查询,链接查询与分组类似,都是生成了一个新的表,其执行顺序也类似。

(11)一些其他功能
使用一个表中的数据更新另外一个表中的数据:update goods as g inner join goods_cates as c on g.catename=c.name set g.catename=c.id;
用于关联的字段应与要关联的其他表中的字段类型一致。

将一个字段设置为外键:alter table tabname add foreign key (fieldname) references tabname1(fieldname1); 注意若添加之前有限制之外的数据则无法添加外键,但是外键极大影响性能,因此一般不使用,删除外键alter table tabname drop foreign key (goods_ibfk_1);括号内为数据库生成的名字。

在创建表时可以直接将数据写入,create table tabname (id...,name...) select fieldname from tabname1 as name from....注意,创建的字段名必须与要写入数据的表的字段名相同,若不相同则需要使用别名。

开启时间统计功能:set profiling=1; 查看消耗时间 show profiles;

SQL注入:通过一定的手段判断服务器类型和后台数据库类型,在特定的位置输入特殊的字符,使其与SQL语句组成新的查询语句(即改变了指令),可以做到以非法的身份获取信息或执行操作,可以将输入的参数加入列表,让execute语句自己解析参数,也可使用PreparedStatement(处理输入不再对sql语句解析)/正则过滤/字符串过滤等方法来防止。
例如select * from goods where name = '...';name的值让用户自己填写,若用户填写' or 1=1 or '1,则组成的sql语句为select * from goods where name = '' or 1=1 or '1',即会将表中所有数据全部查询出来。

MySQL的远程访问:修改/etc/mysql/mysql.conf.d/mysqld.cnf,其中bind-address修改为本机IP而非127.0.0.1,并且对要访问的主机的IP进行权限设置。

:以上为mysql的一些简单操作,详细操作可以参看课本或网上教程。

你可能感兴趣的:(数据库基础)