当前物理的数据库都是按照E-R模型进行设计的,
• E表示entry,实体
• R表示relationship,关系
• 一个实体转换为数据库中的一个表
关系描述两个实体之间的对应规则,包括: 一对一 ,一对多, 多对多
对于设计数据库提出了一些规范,这些规范被称为范式。
• 第一范式(1NF):列不可拆分 , 即无重复的域。指数据库表的每一列都是不可分割的基本数据项。 符合第一范式的特点就有:有主关键字、主键不能为空、主键不能重复,字段不可以再分。
• 第二范式(2NF):唯一标识 ,即拥有实体的唯一标识(eg: 身份证、id号等)。指每个表必须有且仅有一个数据元素为主关键字(Primary key),其他数据元素与主关 键字一一对应。这种关系为函数依赖。
符合第二范式的特点就有:满足第一范式的前提下,消除部分函数依赖。
• 第三范式(3NF):引用主键 ,即每列数据都与主键直接相关。不存在非主属性对码的传递性依赖以及部分性依赖 。
说明:关系型数据库有六种范式。一般说来,数据库只需满足第三范式(3NF)就行了。三大范式只是一般设计数据库的基本理念,可以建立冗余较小、结构合理的数据库。如果有特殊情况,当然要特殊对待,数据库设计最重要的是看需求跟性能,需求>性能>表结构。所以不能一味的去追求范式建立数据库。
简介
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数据库
服务端操作:
select Host,User,Passwod from mysql.user
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 ;
create table 表名(列及类型);
例如:
create table userinfo(
-> username varchar(20) not null unique,
-> passwd varchar(20) not null);
两列:username、passwd username的类型为字符串可变长字节是20 不可为空、唯一
alter table userinfo change sex gender varchar(20);
alter table userinfo add sex varchar(20);
alter table userinfo drop gender;
rename table userinfo to users;
show tables;
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)
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;
select * from 表名 where 条件;
# 查询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 gender from students;
#查询students中不重复的sex(消除重复)
select distinct ssex from students;
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);
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;
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;
语法顺序总结:
执行顺序为:
#练习题:
# 查询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 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库, Python2中则使用MySQLdb。
安装: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数据库
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()