Navicat内部封装了所有的操作数据库的命令,用户只需要点击操作即可,无需书写sql语句。
navicat能够充当多个数据库的客户端。
具体操作参考百度。
import pymysql
# 连接数据库
conn = pymysql.connect(
host = ‘127.0.0.1‘,
port = 3306,
user = ‘root‘,
password = ‘123456‘,
database = ‘test1‘, # 操作的库名
charset = ‘utf8‘ # 编码不要加 -
)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 产生一个游标对象(就是用来执行sql语句)
‘‘‘
cursor=pymysql.cursors.DictCursor将查询结果以字典的形式返回
‘‘‘
sql = ‘select * from emp1;‘ # sql语句
res = cursor.execute(sql)
# print(res) # execute返回的结果就是sql语句影响的行数,该返回值一般不使用
# *********************************************************
# 获取执行命令的查询结果
# print(cursor.fetchone()) # 只拿执行这条语句的一条结果
# print(cursor.fetchall()) # 拿执行这条语句的所有结果
# print(cursor.fetchmany(2)) # 指定拿多少条结果
# *********************************************************
# 读取数据类似于光标的移动
# print(cursor.fetchone())
# print(cursor.fetchone())
# print(cursor.fetchall())
‘‘‘
结果:
{‘id‘: 1, ‘name‘: ‘hp‘, ‘sex‘: ‘male‘, ‘age‘: 18, ‘dep_id‘: 200}
{‘id‘: 2, ‘name‘: ‘sj‘, ‘sex‘: ‘female‘, ‘age‘: 20, ‘dep_id‘: 201}
[{‘id‘: 3, ‘name‘: ‘mzx‘, ‘sex‘: ‘female‘, ‘age‘: 22, ‘dep_id‘: 202}, {‘id‘: 4, ‘name‘: ‘tank‘, ‘sex‘: ‘male‘, ‘age‘: 21, ‘dep_id‘: 203}, {‘id‘: 5, ‘name‘: ‘who‘, ‘sex‘: ‘male‘, ‘age‘: 24, ‘dep_id‘: 204}]
‘‘‘
# *********************************************************
# 控制光标的移动
print(cursor.fetchone())
print(cursor.fetchone())
# cursor.scroll(1,‘relative‘) # 相对光标当前位置再往后移动一位 ,relative当前位置,所有id=3的数据没有了
cursor.scroll(1,‘absolute‘) # 相对光标开头位置往后移动一位,absolute开头位置
print(cursor.fetchall())
‘‘‘
结果:
cursor.scroll(1,‘relative‘) 的执行结果
{‘id‘: 1, ‘name‘: ‘hp‘, ‘sex‘: ‘male‘, ‘age‘: 18, ‘dep_id‘: 200}
{‘id‘: 2, ‘name‘: ‘sj‘, ‘sex‘: ‘female‘, ‘age‘: 20, ‘dep_id‘: 201}
[{‘id‘: 4, ‘name‘: ‘tank‘, ‘sex‘: ‘male‘, ‘age‘: 21, ‘dep_id‘: 203}, {‘id‘: 5, ‘name‘: ‘who‘, ‘sex‘: ‘male‘, ‘age‘: 24, ‘dep_id‘: 204}]
cursor.scroll(1,‘absolute‘) 的执行结果
{‘id‘: 1, ‘name‘: ‘hp‘, ‘sex‘: ‘male‘, ‘age‘: 18, ‘dep_id‘: 200}
{‘id‘: 2, ‘name‘: ‘sj‘, ‘sex‘: ‘female‘, ‘age‘: 20, ‘dep_id‘: 201}
[{‘id‘: 2, ‘name‘: ‘sj‘, ‘sex‘: ‘female‘, ‘age‘: 20, ‘dep_id‘: 201}, {‘id‘: 3, ‘name‘: ‘mzx‘, ‘sex‘: ‘female‘, ‘age‘: 22, ‘dep_id‘: 202}, {‘id‘: 4, ‘name‘: ‘tank‘, ‘sex‘: ‘male‘, ‘age‘: 21, ‘dep_id‘: 203}, {‘id‘: 5, ‘name‘: ‘who‘, ‘sex‘: ‘male‘, ‘age‘: 24, ‘dep_id‘: 204}]
‘‘‘
import pymysql
conn = pymysql.connect(
host = ‘127.0.0.1‘,
port = 3306,
user = ‘root‘,
password = ‘123456‘,
database = ‘test1‘,
charset = ‘utf8‘,
autocommit = True
)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 增
sql = ‘insert into user(username,password) values(%s,%s);‘
# rows = cursor.execute(sql,(‘曦曦‘,‘123456‘)) # 增加一条数据
rows = cursor.executemany(sql,[(‘曦曦‘,‘123456‘),(‘木子曦‘,‘123456‘)]) #增加多条数据
print(rows)
conn.commit() # 二次确认
# 修改
# sql = ‘update user set username="hp_1" where id=1;‘
# rows = cursor.execute(sql)
# print(rows)
# conn.commit() # 二次确认
# 删除
# sql = ‘delete from user where id=1;‘
# rows = cursor.execute(sql)
# print(rows)
# conn.commit() # 二次确认
# 查
# sql = ‘select * from user;‘
# cursor.execute(sql)
# print(cursor.fetchall())
‘‘‘
由上面代码结果可以看出(除查有结果,其余都没有结果)
增删改-涉及到操作数据的修改
1. 需要二次确认 conn.commit()
2. 如果不想二次确认,在连接数据库加入 autocommit = True
‘‘‘
‘‘‘
利用语法的特性,通过书写特定的语句实现固定的语法
MySQL利用MySQL的注释语法
select * from user where username=‘hp‘ -- 516515‘ and password=‘‘;
或者
select * from user where username=‘xxx‘ or 1=1 -- 215535‘ and password=‘‘;
‘‘‘
在日常生活中很多软件在注册的时候都不能包含特殊的符号,因为怕你构造出特定的语句入侵数据库
# 解决办法:
‘‘‘
铭感的数据不要自己做拼接,交个execute帮你拼接即可
‘‘‘
import pymysql
# 连接数据库
conn = pymysql.connect(
host = ‘127.0.0.1‘,
port = 3306,
user = ‘root‘,
password = ‘123456‘,
database = ‘test1‘, # 操作的库名
charset = ‘utf8‘ # 编码不要加 -
)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
username = input(‘>>>:‘).strip()
password = input(‘>>>:‘).strip()
sql = "select * from user where username=%s and password=%s;"
# 不要手动拼接数据,先用%s占位之后将需要拼接的数据直接交个execute方法即可
rows = cursor.execute(sql,(username,password)) # 自动识别sql里面的%s用作后面元组里面的数据替换
#print(sql)
if rows:
print(‘登陆成功‘)
print(cursor.fetchone())
else:
print(‘账号或密码错误!‘)
视图就是通过sql语句查询得到的一张虚拟表保存下来,下次可以直接使用。
其实视图也是表。
如果频发的操作一张虚拟表(拼表组成的),可以制成视图,以便后续操作。
# 固定语法
create view 表名 as 虚拟表的查询sql语句
# 具体操作
create view employee as
select * from emp1 inner join dep on emp1.dep_id=dep.id;
‘‘‘
1 创建视图在硬盘上只会有表结构,没有表数据(数据还是来源于原来的表)
2 视图一般只用来查询里面的数据,不要修改。修改可能会影响原来表的数据。
‘‘‘
在满足对表数据进行增、删、改的情况下,自动触发的功能
使用触发器可以帮助我们实现监控、日志等。
触发器可以在六种情况下自动触发,增前、增后、删前、删后、改前、改后。
create trigger 触发器名字 before/after insert/update/delete on 表名 for each row
begin
sql语句
end
# 具体使用 针对触发器的名字 通常需要做到见名知意
# 针对增(其他类似)
create trigger tri_before_insert_t1 before insert on t1 for each row
begin
sql语句
end
create trigger tri_after_insert_t1 after insert on t1 for each row
begin
sql语句
end
delimiter $$ 将默认的结束符由;改为$$ 只作用于当前窗口
# 模拟错误日志功能
# 创建表
create table cmd (
id int primary key auto_increment,
user char(32),
priv char(10),
cmd char(64),
sub_time datatime,#提交时间
success enum(‘yes‘,‘no‘)#0代表执行失败
);
create table errlog (
id int primary key auto_increment,
err_cmd char(64),
err_time datatime
);
‘‘‘
cmd表中记录succes字段是no就触发触发器的执行errlog表中的插入数据
NWE指代的是一条条数据对象,NEW.success指的是cmd表中的success字段
‘‘‘
# 创建触发器
# 修改结束符防止if语句错误
delimiter $$
create trigger tri_after_insert_cmd after insert on cmd
for each row
begin
if NEW.success = ‘no‘ then
insert into errlog(err_cmd,err_time)
values(NEW.cmd,NEW.sub_time);
end if;
end $$
delimiter ;
# 往cmd 表插入数据
# NOW()获取当前时间
insert into cmd(user,priv,cmd,sub_time,success)
values
(‘hp‘,‘0010‘,‘ls -l /etc‘,NOW(),‘yes‘),
(‘hp‘,‘0010‘,‘cat /etc/passwd‘,NOW(),‘no‘),
(‘hp‘,‘0010‘,‘useradd xxx‘,NOW(),‘no‘),
(‘hp‘,‘0010‘,‘ps aux‘,NOW(),‘yes‘);
# 删除触发器
drop trigger tri_after_insert_cmd;
什么是事务:
开启一个事务可以包含多条sql语句,这些sql语句要么同时成功,要么同时失败。
事务的作用:
保证对数据的安全性。
事务的四大特性:
‘‘‘
简称ACID
A:原子性
一个事务是一个不可分割的单位,事务中包含的诸多操作
要么同时成功要么同时失败
C:一致性
事务必须是使数据库从一个一致性的状态变到另外一个状态
一致性跟原子性密切相关的
I:隔离性
一个事务的执行不能被其他事务干扰。
一个事务内部的操作及使用到的数据对并发的其他事务是隔离的,并发执行的事务也是互不干扰。
D:持久性(永久性)
一个事务一旦提交成功执行成功,那么它对数据中数据的修改是永久的,接下来的其他操作或故障不应该对其有任何影响。
‘‘‘
# 事务相关的关键字
# 1. 开启事务
start transaction;
# 2. 回滚(回到事务执行之前的状态)
rollback;
# 3. 二次确认(确认之后无法回滚)
commit;
‘‘‘模拟转账功能‘‘‘
create table user(
id int primary key auto_increment,
name char(16),
balance int
);
insert into user(name,balance) values
(‘hp‘,1000),
(‘sj‘,1000),
(‘mzx‘,1000);
# 1 开启事务
start transaction;
# 2 书写多条sql语句
update user set balance=900 where name=‘hp‘;
update user set balance=1090 where name=‘sj‘;
update user set balance=1010 where name=‘mzx‘;
# 3 取消或确认(二选一)
rollback;
or
commit;
存储过程类似于python中的自定义函数
它内部包含了一系列的可以执行的sql语句,存储过程存放于MySQL服务端中,可以直接通过调用存储过程触发内部SQL语句的执行。
create procedure 存储过程的名字()
begin
sql代码
end
#调用
call 存储过程的名字();
第一种
‘‘‘
应用程序:程序员写代码开发
MySQL:提前编写好存储过程,供应用程序调用
好处:开发效率提升,执行效率提升
缺点:考虑到人为因素、跨部门沟通的问题,后续的存储过程的扩展性差。
‘‘‘
第二种
‘‘‘
应用程序:程序员写代码开发,设计到数据库操作也是自己动手
好处:扩展性高
缺点:开发效率低,编写sql语句太过繁琐,后续还要对SQL语句优化。
‘‘‘
第三种
‘‘‘
应用程序:只写程序代码,不写sql,基于别人写好的操作MySQL的python框架直接调用操作 ORM框架
好处:开发效率比上面两种情况都要高
缺点:语句的扩展性差,可能会出现效率低的问题
‘‘‘
总结:第一种基本不用,一般都是使用第三种,出现效率问题再动手写sql语句。
delimiter $$
create procedure p1(
in m int, # in只进不出 m不能返回出去
in n int,
out res int # out该形参可以返回出去
)
begin
select name from user where id>m and id < n;
set res = 666; # 将res变量修改 用来标识当前的存储过程代码确实执行
end $$
delimiter ;
# 针对形参res 不能直接传数据,应传一个变量名
# 定义变量
set @ret = 10;
# 查看变量对应的值
select @ret;
# 调用
call p1(1,3,@ret)
import pymysql
# 连接数据库
conn = pymysql.connect(
host = ‘127.0.0.1‘,
port = 3306,
user = ‘root‘,
password = ‘123456‘,
database = ‘test1‘, # 操作的库名
charset = ‘utf8‘ # 编码不要加 -
)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 调用存储过程
cursor.callproc(‘p1‘,(1,3,10))
‘‘‘
传递值的过程
@_p1_0=1
@_p1_1=3
@_p1_2=10
‘‘‘
# print(cursor.fetchall())
cursor.execute(‘select @_p1_2;‘)
print(cursor.fetchall())
与存储过程是有区别的,存储过程是自定义函数,这个函数类似于内置函数。
例如:
(‘hp‘,‘0010‘,‘ls -l /etc‘,NOW(),‘yes‘)
NOW()就是内置函数
# if 判断
delimiter $$
create procedure proc_if()
begin
declare i int default 0;
if i = 1 then
select 1;
elseif i = 2 then
select 2;
else
select 7;
end if;
end $$
delimiter ;
# while循环
delimiter $$
create procedure proc_while()
begin
declare num int;
set num = 0;
where num < 10 do
select
num ;
set num = num + 1;
end while;
索引:就是一种数据结构,类似于书的目录。意味着查询数据的时候先找目录再找数据,从而提升查询速度降低IO操作。
索引在MySQL中也叫" 键 ",是存储引擎用于快速查找记录的一种数据结构。
注意:foreign key 不是用来加速查询用的。
上面的三种key ,前面两种除了加快查询速度还具有约束条件,而最后一种index key没有任何约束条件,只是用来加快查询速度。
通过不断的缩小查询数据的范围筛选出最终的结果,同时将随机事件(整体查询)变成顺序事件(先找目录,再找数据)。
有了索引机制,总是用一种固定的方式查找数据。
一张表中可以有多个索引(多个目录)
缺点
‘‘‘
1 当表中有大量数据存在的前提下 创建索引速度会很慢
2 在索引创建完毕之后 对表的查询性能会大幅度的提升,但是写的性能也会大幅度的降低
‘‘‘
索引不要随意的创建
‘‘‘
只有叶子节点存放的是真实的数据,其他节点存放的是虚拟数据(仅仅是用来指路的)
树的层级越高查询数据所需的步骤越多(树有几层查询的步骤就有几步)
一个磁盘块的存储是有限制的
建议使用id作为索引,是因为占的空间少,一个磁盘存储的数据多从而降低树的高度,减少查询次数
‘‘‘
聚集索引指的就是主键
Innodb 只有两个文件,直接减主键存放在idb表中
MyIsam 三个文件,单独将索引存在一个文件中
查询数据的时候不可能一直使用主键,也可能用到其他字段,那么无法使用聚集索引,这个时候,可以根据情况使用辅助索引。
‘‘‘
叶子节点存放的数据对应的主键值
先按照辅助索引拿到数据的主键值,
再去主键的聚集索引查找数据。
‘‘‘
在辅助索引的叶子节点已经达到所需的数据,这种现象叫做覆盖索引。
# 覆盖索引,给name 设置辅助索引
select name from user where name=‘hp‘;
# 非覆盖索引
select balance from user where name = ‘hp‘;
原文:https://www.cnblogs.com/hp-mzx/p/14506466.html