(以下所有操作使用的均为Mac系统+pycharm为IDE,需要有数据库理论基础和sql语法知识)
目录
1.终端sql操作(mysql数据库)
--连接数据库
mysql -uroot -p (后输入mysql密码即可)
--退出数据库
exit/quit/ctrl+d
(sql语句不区分大小写,每句后面都必须有;)
--查看所有数据库
mysql>show databases;
--显示时间
select now();
--显示数据库版本
select version();
--创建数据库
create database python-04;
--查看创建数据库语句
show create database python04;
--删除数据库
drop database python-04;(会报错,因为系统默认将-04识别为新的一部分数据,而我们需要python-04作为整体)
改为:drop database `python-04`;
--查看当前使用的数据库
select database();
--使用数据库
use python-04;
--(选择需要修改的数据库后)创建表
create table lilho(id int unsigned primary key not null auto_increment, name varchar(20));(可换行)
create table lilho(
id int primary key not null auto_increment,
name varchar(20)
gender enum("male","female","secret") default "secret"
);
--查看所有表
show tables;
--查看表结构
desc lilho;
--查看系统创建表语句(格式化你新建表的语句)
show create table lilho;
--修改表结构
①重命名:alter table 表名 change 原名 新名 类型及约束;
②不重命名:alter table 表名 modify 列名 类型及约束;
③增加列:alter table 表名 add 列名 类型及约束;
④删除列:alter table 表名 drop 列名;
⑤增删外键:alter table 表名 add foreign key (外键名) references 引用表名(引用列名);
alter table 表名 drop foreign key 外键名;
--插入数据
insert into lilho values(0,"sdhg"); 整体插入,一一对应
insert into lilho (name) values("shjgd"); 部分插入,先写列名,再输入数值;并且可以同时添加多个
如果是从另一个表中选择数据插入到新表中,不需要values关键字:
insert into lilho (name, age) select cname,cage from anther_table;
--查询后的结果一列中显示多种信息
select group_concat(name,"_",id) from lilho;
--分页
limit start,num;(从start+1开始显示,num为显示的个数,无论查询的个数是多少,只显示不超过num个,start可以省略,默认从0开始搜索)
用limit语句实现分页:limit (第N页-1)*每页的个数, 每页的个数;
顺序:where,order by, limit(不可以将order by 放在limit后面)
--读取数据
将.sql文件读进数据库中,使用source + 文件名.sql
--子母表同时更新数据
(假设goods_cates是母表,包含三列;goods是子表,两列都是从goods_cates取出来的列,通过内连接和update语句进行同步跟新)
update goods as g inner join goods_cate as c on g.ganame = c.cname set g.cate_name = c.id;
--创建用户并授予权限
grant 权限列表 on 数据库 to '用户名'@'访问主机' identied by '密码';
--备份
mysqldump -uroot -p 数据库名 > 文件名.sql (“>”表示重定向输出)
--恢复
mysql -uroot -p 新建数据库名 < 文件名.sql
(其他sql语句自行学习数据库相关知识)
2.mysql和python交互
-
安装模块
sudo pip3 install pymysql
-
引入模块
from pymysql import *
-
Connection对象
用于建立与数据库的连接。
conn = connect(参数列表)
参数host:连接的mysql主机,如果是本机为'localhost'
参数port:连接的mysql主机的端口,默认为3306
参数database:database的名称
参数user:连接的用户名
参数password:连接的密码
参数的charset:通信采用的编码方式,推荐使用utf8(python3.8中不需要传递该参数)
对象方法:
.close() 关闭连接
.commit() 提交
.rollback() 返回,在提交前可以返回到上一次提交时的数据库内容,当前的sql操作不起作用。
.cursor() 返回Cursor对象,用于执行sql语句并返回结果
-
Cursor对象
用于执行sql语句,通过connect对象的.cursor()方法获取一个实例。
sc1 = conn.cursor()
对象方法:
.close() 关闭
.execute("执行语句") 返回受影响的行数
.fetchone() 执行查询时,获取查询结果集的第一个行数据,返回一个元组,当多次调用时依次往下获取结果
.fetchall() 执行查询时,获取结果集的所有行。一行构成一个元组,再将这些元组装入一个元组返回
对象属性:
.rowcount 只读属性,表示最近一次执行语句后影响的行数
.connection 获取当前的连接对象
简单举例:
目前操作的数据库如下:
from pymysql import *
conn = connect(host='localhost', port=3306, user='root', password ='880117', database='hsj')
cs = conn.cursor()
mysql_insert = 'insert into lilho values(0,"hsdj",12,"female");'
cs.execute(mysql_insert)
sql = "ALTER TABLE lilho AUTO_INCREMENT = 1;"
cs.execute(sql)
count = cs.execute("select * from lilho;")
for i in range(count):
print(cs.fetchone())
# 如果有增删改操作需要将修改提交给数据库
conn.commit()
cs.close()
conn.close()
运行结果:
(1, 'hsj', 23, 'male')
(2, 'shd', None, 'secret')
(3, 'hsdj', 12, 'female')
-
mysql命令参数
如果数据复杂,组合的sql语句可能无效(如字段汇总含有双引号),因此可以带参数的execute命令:
cursor.execute(带参数的SQL命令,(参数列表))
其中带参数的sql命令是sql把不缺的参数值用参数%s表示,参数列表是对应的参数的值,放在一个元组或列表中。
3.python与sqlite交互
sqlite是一种轻型数据库,它的设计目标是嵌入式的,并且python3自带对sqlite的支持。引入模块后,除了在sqlite中,数据库参数不是%s改为了?,其他操作与mysql基本相同(sqlite的数据类型简单一点)。
-
引入模块
import sqlite3
-
连接数据库
con = sqlite3.connect("test.db") # test.db是sqlite3数据文件
-
操作数据库
cs = con.cursor()
cs.execute(SQL)
con.submit()
cs.close()
con.close()
举例说明:建立一个学生数据库students.db,并创建一张学生记录表students,包含学号Sno,姓名Sname,性别Sgender,年龄Sage字段。
import sqlite3
sql = """
create table students
(
Sno int unsigned primary key not null,
Sname varchar(16),
Sgender varchar(6) default "secret",
Sage int unsigned
)
"""
con = sqlite3.connect("students.db")
cs = con.cursor()
cs.execute(sql)
cs.execute('insert into students values(1, "小明", "male", 13),(2,"小红","female",15),(3, "小凯", "secret", 14)')
cs.execute("select * from students")
rows = cs.fetchall()
for row in rows:
print(row[0], row[1], row[2])
con.commit()
cs.close()
con.close()
运行结果:
1 小明 male
2 小红 female
3 小凯 secret
4. sql注入
sql注入可以理解为与用户交互时,用户恶意输入恒为true的代码来窃取信息(如'or 1=1')。
简单的解决方案:将用户输入的信息传进列表中,让execute函数自动拼装,而不是采用python字符串填充的方法。
# 会导致sql注入
sql = 'select * from lilhoe where name = "{}";'.format(input());
cursor.execute(sql)
# 不会导致sql注入
input_list = [input()]
sql = 'select * from lilhoe where name = {};'
cursor.execute(sql, input_list)
5. sql索引
索引是一种特殊的文件,InnoDB数据表上的索引是表空间的一个组成部分(linux采用的是InnoDb数据表),它们包含着对数据表里所有记录的引用指针)。
下面通过一个demo来体会一下建立索引之后查找的快速:
- 首先从终端创建一个测试表:test_index
create table test_index(title varchar(20));
- 通过python插入100000条数据:
from pymysql import *
conn = connect(host='localhost', port=3306, user='root', password ='880117', database='hsj')
cs = conn.cursor()
for i in range(10000):
cs.execute("insert into test_index values('ha{}')".format(i))
conn.commit()
cs.close()
conn.close()
- 在终端开启所有工作的时间统计功能:
set profiling = 1;
- 查询第100000条数据:
select * from test_index where title = "ha99999";
- 查看执行时间:
show profiles;
- 可以查看当刚刚查询语句执行的时间:
- 为表test_index的title字段建立一个索引:
--title是字符串类型,所以需要加入长度
create index title_index on test_index(title(20));
- 再一次执行查询第100000条语句,并查看执时间:
比较两次的时间可以得出结论:在需要查找的字段建立索引后,查找速度明显提高。
注意:
建立太多的索引会影响插入和更新的速度,因为它同样需要更新每个索引文件,且建立索引会占用磁盘空间。