关系型数据库MySQL

文章目录

  • 数据库简介
  • 关系型数据库
    • E-R模型
    • 范式
    • MySQL简介与安装
  • 数据库基本操作
  • 数据库表基本操作
  • 数据基本操作
  • 数据查询操作
  • 小练习题
  • pymysql数据库编程
  • sqlite数据库

数据库简介

  • 为什么需要数据库?
    人类在进化的过程中,创造了数字、文字、符号等来进行数据的记录,但是承受着认 知能力和创造能力的提 升,数据量越来越大,对于数据的记录和准确查找,成为了一个 重大难题。数据库系统解决的问题:持久化存储,优化读写,保证数据的有效性。
  • 数据库分类
    关系型数据库: 指采用了关系模型来组织数据的数据库。关系模型指的就是二维表格模型,而一 个关系型数据库就是由二维表及其之间的联系所组成的一个数据组织。主流的关系型数据库有: Oracle、Microsoft SQL Server、MySQL、PostgreSQL,SQLite、MariaDB(MySQL的一个分 支)Microsoft Access、SAP。
    非关系型数据库:指非关系型的,分布式的,以键值对存储且结构不固定,可以减少一些时间和空间的开销。非关系型数据库都是针对某些特定的应用需求,主要分为以下几类: 1). 面向海量数据访问的面向文档数据库:MongoDB、Amazon DynamoDB、Couchbase等。 2). 面向高性能并发读写的key-value数据库: Redis、 Memcached等。 3). 面向搜索数据内容的搜索引擎:Elasticsearch,Splunk,Solr,MarkLogic和Sphinx等。 4). 面向可扩展性的分布式数据库:Cassandra,HBase等。

关系型数据库

E-R模型

当前物理的数据库都是按照E-R模型进行设计的,
• E表示entry,实体
• R表示relationship,关系
• 一个实体转换为数据库中的一个表
关系描述两个实体之间的对应规则,包括: 一对一 ,一对多, 多对多

范式

对于设计数据库提出了一些规范,这些规范被称为范式。
• 第一范式(1NF):列不可拆分 , 即无重复的域。指数据库表的每一列都是不可分割的基本数据项。 符合第一范式的特点就有:有主关键字、主键不能为空、主键不能重复,字段不可以再分。
• 第二范式(2NF):唯一标识 ,即拥有实体的唯一标识(eg: 身份证、id号等)。指每个表必须有且仅有一个数据元素为主关键字(Primary key),其他数据元素与主关 键字一一对应。这种关系为函数依赖。
符合第二范式的特点就有:满足第一范式的前提下,消除部分函数依赖。
• 第三范式(3NF):引用主键 ,即每列数据都与主键直接相关。不存在非主属性对码的传递性依赖以及部分性依赖 。
说明:关系型数据库有六种范式。一般说来,数据库只需满足第三范式(3NF)就行了。三大范式只是一般设计数据库的基本理念,可以建立冗余较小、结构合理的数据库。如果有特殊情况,当然要特殊对待,数据库设计最重要的是看需求跟性能,需求>性能>表结构。所以不能一味的去追求范式建立数据库。

MySQL简介与安装

  • 简介
    MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗 下产品。MySQL 是最流行的关系型数据库管理系统之一。
    MySQL常用存储引擎分析:
    数据库存储引擎是数据库底层软件组织,进行创建、查询、更新和删除数据。不同的存储引 擎提供不同的存储机制、索引技巧、锁定水平等功能, MySQL的核心就是存储引擎。 MySQL查询存储引擎SQL语句:SHOW ENGINES

  • linux下安装步骤
    yum search mariadb > yum install mariadb-server.x86_64 > systemctl start mariadb > mysql_secure_installation(为数据库添加密码)

  • 允许其他主机远程连接当前主机的mysql
    客户端: 172.25.254.18
    服务端:172.25.254.12
    需求:客户端18可以远程连接服务端12数据库
    服务端操作:

  1. 服务端关闭mysql服务器的防火墙:systemctl stop firewalld > systemctl disable firewalld
  2. 登陆自己的数据库:mysql -uroot -p
  3. 查看mysql中数据库表user的三列(查看此时都有谁可以连接服务端数据库):select Host,User,Passwod from mysql.user
  4. 允许客户端以root身份密码为westos授权登陆,%表示任意 ip ; * .* 表示所有数据库中的所有数据库表: grant all on *.* to root@'%' identified by 'westos';
    客户端测试:
    mysql -h 172.25.254.18 -uroot -pwestos #以root身份密码为westos登陆服务端18的mysql数据库

删除远程登陆指定的用户授权:drop user root@'%'; %:任意用户 %换成指定ip表示删除指定用户的登陆授权。

数据库基本操作

  • 创建数据库
    create database 数据库名 default charset=‘utf8’;#创建数据库可存储中文
  • 查看数据库
show databases;
  • 切换数据库
 use 数据库名;
  • 删除数据库
 drop database 数据库名;
  • 查看当前所使用的数据库
 select database();

数据库表基本操作

  • 查看当前数据库中的所有表
show tables ;
  • 创建表: 一个数据库就是一个完整的业务单元,可以包含多张表,数据被存储在表中,在表中为了更加准确的存储数据,保证数据的正确有效,可以在创建表的时候,为 表添加一些强制性的验证, 包括数据字段的类型、约束
  • 字段类型
    在mysql中包含的数据类型很多,这里主要列出来常用的几种:
    • 数字:int,decimal, float
    • 字符串:varchar,text
    • 日期:datetime
    • 布尔:bool
  • 约束
    • 主键 primary key
    • 非空 not null
    • 惟一 unique
    • 默认 default
    • 外键 foreign key
    • 自动增长 auto_increment
create table 表名(列及类型); 

例如:

create table userinfo(
    -> username varchar(20) not null unique,
    -> passwd    varchar(20) not null);
 

两列:username、passwd username的类型为字符串可变长字节是20 不可为空、唯一

  • 将原先表中 sex一列改为gender
alter table userinfo change  sex gender  varchar(20);
  • 为原先表userinfo添加一列sex
alter table userinfo add sex varchar(20);
  • 删除userinfo中的gender列
alter table userinfo drop gender;
  • 将表名称userinfo修改为users
rename table userinfo to users;
  • 查看当前数据库的所有表
show tables;
  • 查看创建当前表的sql语句
show create table '表名';
  • 删除表
 drop table 表名;
  • 查看表结构
desc 表名;

数据基本操作

  • 创建表结构:
create table users(id int primary key auto_increment,username varchar(20)not null unique,passwd    varchar(20) not null)
  • 查看uers的数据,此时为空
select * from users;
  • 向表中增加数据信息:
 insert into users values('1','user1','666'); #全列插入表信息
insert into users(username) values('user2'),('user3');#同时插入2条数据。针对username这一列插入内容为user2,其余列自动插入默认值,
  • 向表中更改数据信息:
 update users  set passwd='235' where username='user2'; #对表users将user2的passwd改为235 where后接指定条件
select * from users where username='user1' ;#指定查看表users内容为uesr1的数据信息
  • 向表中删除数据信息:
 delete from users where username='user1'; #删除表users中user1的信息
  • 数据备份与恢复
mysqldump -uroot -pwestos 要备份的数据库名 > 新的备份文件.sql #备份
mysql -uroot -pwestos 本地存在的数据库名 < 备份文件.sql # 恢复:此处数据库名为要恢复的电脑中的数据库,备份文件.sql前面要加绝对路径。

数据查询操作

  • 查询的基本语法
select * from 表名;

from关键字后面写表名,表示数据来源于是这张表
select后面写表中的列名,如果是*表示在结果中显示表中所有列
在select后面的列名部分,可以使用as为列起别名,这个别名出现在结果集中
如果要查询多个列,之间使用逗号分隔

use studentproject;
#将students表中的列sno与列sname以number与name显示出来 (列的重命名)
select sno as number,sname as name from students;
  • 查询的筛选条件
    使用where子句对表中的数据筛选,结果为true的行会出现在结果集中
    select * from 表名 where 条件;
    优先级
    •小括号,not,比较运算符,逻辑运算符
    •and比or先运算,如果同时出现并希望先算or,需要结合()使用
    关系型数据库MySQL_第1张图片
# 查询scores表中成绩在60--80之间的记录 (筛选条件)
 select * from scores where degree between 60 and 80;
# 查询scores表中成绩为85,86,87的记录
 select * from scores where degree in (85,86,87);
  • 查询消除重复行
    在select后面列前使用distinct可以消除重复的行
 select distinct gender from students;
#查询students中不重复的sex(消除重复)
select distinct ssex from students;
  • 查询的分组
    • 按照字段分组,表示此字段相同的数据会被放到一个组中
    • 分组后,只能查询出相同的数据列,对于有差异的数据列无法出现在结果集中
    • 可以对分组后的数据进行统计,做聚合运算,为了快速得到统计数据,提供了5个聚合函数:
    关系型数据库MySQL_第2张图片
select 列1,列2,聚合... from 表名 group by 列1,列2,列3...
#查询班级为9503的学生总人数
select count(*) as studentcount from students where class='9503';
#查询编号为3-105的学生成绩平均数
select avg(degree) as degreeavg from scores where cno='3-105';
  • 分组后的数据筛选
group by xxx having xxx 

having后面的条件运算符与where的相同。
对比where与having
• where是对from后面指定的表进行数据筛选,属于对原始数据的筛选
• having是对group by的结果进行筛选
筛选条件先计算再判断使用group by先分组,对原始数据直接判断使用where,where是对from后面指定的表进行数据筛选,属于对原始数据的筛选

# 查询socres表中drgree大于70小于90的sno列
 select sno from scores where degree >70 and degree <90 ;

# 查询scores表中至少有5名学生选修的并以3开头的课程和对应的平均分数,
#分析:
# 课程和对应的平均分数都有一个共有条件:以3开头
# 至少有5名学生选修:count(cno)>=5 课程数大于等于5
# 以3开头的课程:cno like '3%' (不用计算使用where)
# 课程的平均分数:avg(degree)
 select cno,avg(degree) from scores where cno like '3%' group by cno having count(cno)>=5;

# 查询scores中选学1门以上的课、分数为非最高分成绩的同学
#分析:
# 选学1门以上课:count(cno) >1
# 分数为非最高分成绩:degree != max(degree)
# 分组  按照学生分组 学生的条件为:选学1门以上课、分数为非最高分成绩
 select * from scores group by sno having count(cno)> 1 and degree != max(degree);
  • 对数据进行排序:
    默认按照列值从小到大排列
    asc从小到大排列,即升序, desc从大到小排序,即降序
 order by  xxx/xxx desc
#查询students表中以class为降序的内容
select * from students order by class desc;
#查询students表中以class为生序的内容
select * from students order by class ;
#查询scores表中cno为生序degree为降序的内容(此时cno相同时degree为降序显示)
select * from scores order by cno,degree desc;
  • 获取部分行
    当数据量过大时,在一页中查看数据是一件非常麻烦的事情:
    • 从start开始,获取count条数据 • start索引从0开始
limit start count
#查询成绩最高的前5名学生信息
select * from scores order by degree limit 5;
select * from scores order by degree desc limit 2,3;从第二个索引开始获取3条数据

#嵌套查找
#查询scores表中最高分的学生学号和课程号
select sno,cno from scores where degree=(select max(degree) from scores);
  • 空判断与模糊查询
#空判断:
insert into courses(cno,cname) values(3-666,'概率论'); #只对前两列输入值对最后一列不输入值
 select * from courses where tno='';#查询最后一列为空时的结果
#模糊查询:_单个字符两个下划线表示两个字符
select  * from courses where cname like '%数学%';#查找包含cname包含数学的内容
select  * from courses where cname like '__数学
  • 多表查询
# 两个表的拼接:
# 查询所有学生的sname、cno和degree列
# 分析:sname、cno在student表中,degree在scores表中,两个表中有相同的列为sno,当两个表中sno相同时拼接其余值。on后跟条件
# 等值拼接:
select sname ,cno ,degree from students inner join scores on students.sno=scores.sno;

# 三个表的拼接:
# 查询所有学生的sname、cname和degree列
# 分析:sname在student表中,cname在courses表中,degree在scores表中,
# student表与scores表中有相同的列为sno,scores表与courses表有相同的列为cno,先拼接两个表在拼接第三个表。
 select sname ,cname ,degree from students inner join scores on students.sno=scores.sno
 inner join courses on scores.cno=courses.cno;

语法顺序总结:
执行顺序为:

  1. from 表名
  2. where …
  3. group by …
  4. select distinct *
  5. having …
  6. order by …
  7. limit star,count

小练习题

#练习题:
# 查询95033班所选课程的平均分
# 分析:degree在scores表中、cname在courses表中,相同的列为cno
 select avg(degree) from scores inner join courses on scores.cno=courses.cno;

# 查询95033班和95031班全体学生的记录
 select *from students where class=95031 or class=95033;

# 查询student表中不姓王的同学记录
 select *from students where sname not  like  '王%';

# 查询所有任课教师的Tname和Depart
select tname,depart from teachers;

# 查询所有未讲课的教师的Tname和Depart
select tname,depart from teachers where prof != '讲师';

# 查询students表中95031班或性别为女的同学记录
select *from students where class=95031 or ssex='女';

pymysql数据库编程

PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库, Python2中则使用MySQLdb。
关系型数据库MySQL_第3张图片
安装:pip install -i https://pypi.douban.com/simple pymysql
pycharm中:pymysql数据库编程两种步骤:
步骤一:

import pymysql
#创建数据库连接,autocommit自动提交修改到数据库(设置为True才可以在数据库中看到修改的内容)
conn=pymysql.connect(host='localhost',user='root',password='westos',db='Blog',port=3306,autocommit=True,charset='utf8')
#创建游标(用于执行sql语句)
cur=conn.cursor()
#执行sql语句
insert_sql='insert into users(username) values ("user7");'
cur.execute(insert_sql)
print('ok')
#关闭游标
cur.close()
#关闭连接
conn.close()

步骤二:

#使用with语句自动关闭 pymysql.connect为上下文管理器可以使用with语句
"""
connect的部分源码为:
Context manager that returns a Cursor(返回一个游标的上下文管理器)
    def __enter__(self):
        warnings.warn(
            "Context manager API of Connection object is deprecated; Use conn.begin()",
            DeprecationWarning)
        return self.cursor()
On successful exit, commit(提交). On exception, rollback(回滚到一开始的操作)
    def __exit__(self, exc, value, traceback):
        if exc:
            self.rollback()
        else:
            self.commit()
"""

#数据库插入修改操作
import pymysql
users=['westos'+str(i) for i in range(100)]
with pymysql.connect(host='localhost',user='root',password='westos',
                     db='Blog',port=3306,autocommit=True,charset='utf8') as cur: #返回一个游标存为cur
    insert_sql='insert into users(username) values ("user9");'
    cur.execute(insert_sql) #执行一条sql语句
    insert_sql='insert into users(username) values ("%s");' #%s占位符
    cur.executemany(insert_sql,users) #执行多条sql语句,values ("%s") %users[0]逐渐递增

    print('ok')
#数据库查询与获取操作
import pymysql
with pymysql.connect(host='localhost',user='root',password='westos',
                     db='Blog',port=3306,autocommit=True,charset='utf8') as cur: #返回一个游标存为cur
    query_sql='select * from users where username like "user%";'#查找username以user开头的内容
    result=cur.execute(query_sql) #cur.execute返回找到的数目
    print('符合条件数为: ',result)
    获取符合条件的内容
    print(cur.fetchone())#获取一条
    print(cur.fetchmany(2))#获取2条 指针移动到获取完第一条的下一条来获取
    print(cur.fetchall())#获取所有
#美观查看内容
from prettytable import PrettyTable
pt=PrettyTable(field_names=['编号','用户','密码'])
for i in cur.fetchall():
    pt.add_row(i)
print(pt)


#执行结果:
符合条件数为:  5
+------+-------+--------+
| 编号 |  用户 |  密码  |
+------+-------+--------+
|  2   | user2 |  235   |
|  3   | user3 | 000000 |
|  4   | user7 | 000000 |
|  5   | user8 | 000000 |
|  6   | user9 | 000000 |
+------+-------+--------+

sqlite数据库

  1. 什么是sqlite数据库?
    SQLite是内嵌在Python中的轻量级、基于磁盘文件袋额数据库管理系统(就是一个文件),
    不需要安装和配置服务,支持使用SQL语句来访问数据库。该数据库使用C语言开发,支持大多数SQL91标准,
    支持原子的、一致的、独立的和持久的事务,不支持外键限制;通过数据库级的独占性和共享性锁定来实现独立事务,
    当多个线程同时访问同一个数据库并试图写入数据时,每一时刻只有一个线程可以写入数据。
  2. sqlite数据库的特性:
      SQLite支持最大140TB大小的单个数据库,每个数据库完全存储在单个磁盘文件中,以B+树数据结构的形式存储,一个数据库就是一个文件,通过直接复制数据库文件就可以实现数据库的备份。如果需要使用可视化管理工具,可以下载并使用SQLiteManager、SQLite Database Browser 或其他类似工具。
#sqlite数据库
import sqlite3
conn=sqlite3.connect(database='users.sqlite')
cur=conn.cursor()
#if not exists如果数据库表不存在时创建表,否则不做任何操作
create_sql='create table if not exists users (id int primary key ,name varchar (10),passwd varchar (10) default "123" );' #id为主键自动递增
cur.execute(create_sql)
insert_sql='insert into users(name) values ("user2");'#对name这一列插入user1
count = cur.execute(insert_sql)
conn.commit() #数据操作(增删改)一定要提交。连接提交修改的语句
select_sql='select * from users' #查询users表的内容
cur.execute(select_sql)
print(cur.fetchall())  #获取表的内容
cur.close()
conn.close()

你可能感兴趣的:(python基础)