Navicat工具、pymysql模块、数据备份

IDE工具介绍(Navicat)

生产环境仍是推荐使用mysql命令行,但为了方便咱们测试,可使用IDE工具,咱们使用Navicat工具,这个工具本质上就是一个socket客户端,可视化的链接mysql服务端的一个工具,而且他是图形界面版的。咱们使用它和直接使用命令行的区别就相似linux和windows系统操做起来的一个区别。html

1、安装和使用

  下载地址:https://pan.baidu.com/s/1bpo5mqjpython

  下载完以后,直接解压出来就能用,看一下解压以后的目录:mysql

  双击打开下面这个文件(能够把它添加一个桌面快捷方式,或者添加到任务栏):linux

  

      而后会提示你输入注册码:sql

      

    回到navicat的解压出来的文件夹里面,有个叫作key.txt的文件,打开,里面有注册码数据库

    

    

    将这个注册码copy到输入注册码的地方:windows

    

    点击肯定就能打开使用了:会显示出来下面的界面后端

    

    

    既然是mysql客户端,咱们须要链接mysql服务端服务器

    

    在弹出的界面输入mysql服务端的ip地址和端口,还有mysql用户名和密码socket

    

    

    

    

    

    

    

    

     

    

    关于校对规则你们看看这两篇博客就明白了:

      http://www.javashuo.com/article/p-xdoxxfej-ew.html

      https://www.jb51.net/article/48775.htm

 

     上面的步骤点击肯定就建好一个数据库了:

    

    而后咱们到上面的数据库里面新建一张表

    

 

     

    

     

    也就是咱们本身用鼠标点啊点之类的,也就是生成对应的sql语句去执行

    而后点击保存:

    

    这个表就生成了:

    

    不信咱们去命令行看一看:这个表就存在了

    

    之后咱们直接就使用这个工具来操做数据库就能够了,由于命令行操做仍是比较恶心的

    而后咱们看看创建外键

    

    

    而后自动会生成对应的sql语句

    

    

     

    

    而后点击保存,起一个表名,就有了这个表了

    

    而后双击上面的表名就能够插入数据了

    

    

    比方说咱们上面这个dep表的id字段没有设置自增,我想改一下,让它这个id字段变为自增的怎么办

    设计表:

    

    

    

    那咱们该怎么办呢,直接删除这个表而后从新建立吗?你另一个关联表确定不让你这么作,因此你须要先将那个关联表的外键关系先取消,或者先将那个外键关联表删除

    

    而后把这个关联表的外键删除,而后保存

    而后再去咱们想给id字段加上自增的那个dep表里面把id字段设置为自增,保存,而后在从新将emp表外键到dep的id字段上

    而后给dep表插入几条数据

    

    

    这个工具还能将你的表之间的关系经过图形的形式来给你展现:

    

    

    点击这个ER图,二者的关系图就显示出来了,那么未来你的表不少的时候,你就能够经过这个图来查看本身表和表之间的关系,看效果:

    

    若是咱们点击两个表之间的线,是能够看到二者之间的关系的:

    

 

    

     还能够选择上面的模型来直接创做图表,建立表之间的关系

    

    

    可是上面咱们创建的这个模型,是不能直接建立到数据库里面的,须要将它以sql的形式导入,而后把导出的sql语句,到数据库里面去执行

    

    而后导出保存到一个地方

    

    打开咱们导出的文件,看一下里面的内容

    

    你看,就是我们建立的模型翻译成的sql语句,复制一下这些sql语句,但mysql里面去执行一下,就等到咱们模型里面的两个表了,是否是很方便

    Navicat工具还能写原生sql语句来进行数据库的操做

    

    就看到一个输入sql语句的界面了:

    

    而后写一个sql语句试一下:

    

    

      而后运行一下:

      

        

      咱们还能够将以前数据库中导出来的数据,以sql文件的形式经过navicat导入到数据库中:看步骤

      假如咱们有一个从数据库中导入的文件,文件名称为init.sql,里面的内容就下面的东东

/*
 数据导入:
 Navicat Premium Data Transfer

 Source Server         : localhost
 Source Server Type    : MySQL
 Source Server Version : 50624
 Source Host           : localhost
 Source Database       : sqlexam

 Target Server Type    : MySQL
 Target Server Version : 50624
 File Encoding         : utf-8

 Date: 10/21/2016 06:46:46 AM
*/

SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
--  Table structure for `class`
-- ----------------------------
DROP TABLE IF EXISTS `class`;
CREATE TABLE `class` (
  `cid` int(11) NOT NULL AUTO_INCREMENT,
  `caption` varchar(32) NOT NULL,
  PRIMARY KEY (`cid`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `class`
-- ----------------------------
BEGIN;
INSERT INTO `class` VALUES ('1', '三年二班'), ('2', '三年三班'), ('3', '一年二班'), ('4', '二年九班');
COMMIT;

-- ----------------------------
--  Table structure for `course`
-- ----------------------------
DROP TABLE IF EXISTS `course`;
CREATE TABLE `course` (
  `cid` int(11) NOT NULL AUTO_INCREMENT,
  `cname` varchar(32) NOT NULL,
  `teacher_id` int(11) NOT NULL,
  PRIMARY KEY (`cid`),
  KEY `fk_course_teacher` (`teacher_id`),
  CONSTRAINT `fk_course_teacher` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`tid`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `course`
-- ----------------------------
BEGIN;
INSERT INTO `course` VALUES ('1', '生物', '1'), ('2', '物理', '2'), ('3', '体育', '3'), ('4', '美术', '2');
COMMIT;

-- ----------------------------
--  Table structure for `score`
-- ----------------------------
DROP TABLE IF EXISTS `score`;
CREATE TABLE `score` (
  `sid` int(11) NOT NULL AUTO_INCREMENT,
  `student_id` int(11) NOT NULL,
  `course_id` int(11) NOT NULL,
  `num` int(11) NOT NULL,
  PRIMARY KEY (`sid`),
  KEY `fk_score_student` (`student_id`),
  KEY `fk_score_course` (`course_id`),
  CONSTRAINT `fk_score_course` FOREIGN KEY (`course_id`) REFERENCES `course` (`cid`),
  CONSTRAINT `fk_score_student` FOREIGN KEY (`student_id`) REFERENCES `student` (`sid`)
) ENGINE=InnoDB AUTO_INCREMENT=53 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `score`
-- ----------------------------
BEGIN;
INSERT INTO `score` VALUES ('1', '1', '1', '10'), ('2', '1', '2', '9'), ('5', '1', '4', '66'), ('6', '2', '1', '8'), ('8', '2', '3', '68'), ('9', '2', '4', '99'), ('10', '3', '1', '77'), ('11', '3', '2', '66'), ('12', '3', '3', '87'), ('13', '3', '4', '99'), ('14', '4', '1', '79'), ('15', '4', '2', '11'), ('16', '4', '3', '67'), ('17', '4', '4', '100'), ('18', '5', '1', '79'), ('19', '5', '2', '11'), ('20', '5', '3', '67'), ('21', '5', '4', '100'), ('22', '6', '1', '9'), ('23', '6', '2', '100'), ('24', '6', '3', '67'), ('25', '6', '4', '100'), ('26', '7', '1', '9'), ('27', '7', '2', '100'), ('28', '7', '3', '67'), ('29', '7', '4', '88'), ('30', '8', '1', '9'), ('31', '8', '2', '100'), ('32', '8', '3', '67'), ('33', '8', '4', '88'), ('34', '9', '1', '91'), ('35', '9', '2', '88'), ('36', '9', '3', '67'), ('37', '9', '4', '22'), ('38', '10', '1', '90'), ('39', '10', '2', '77'), ('40', '10', '3', '43'), ('41', '10', '4', '87'), ('42', '11', '1', '90'), ('43', '11', '2', '77'), ('44', '11', '3', '43'), ('45', '11', '4', '87'), ('46', '12', '1', '90'), ('47', '12', '2', '77'), ('48', '12', '3', '43'), ('49', '12', '4', '87'), ('52', '13', '3', '87');
COMMIT;

-- ----------------------------
--  Table structure for `student`
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `sid` int(11) NOT NULL AUTO_INCREMENT,
  `gender` char(1) NOT NULL,
  `class_id` int(11) NOT NULL,
  `sname` varchar(32) NOT NULL,
  PRIMARY KEY (`sid`),
  KEY `fk_class` (`class_id`),
  CONSTRAINT `fk_class` FOREIGN KEY (`class_id`) REFERENCES `class` (`cid`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `student`
-- ----------------------------
BEGIN;
INSERT INTO `student` VALUES ('1', '', '1', '理解'), ('2', '', '1', '钢蛋'), ('3', '', '1', '张三'), ('4', '', '1', '张一'), ('5', '', '1', '张二'), ('6', '', '1', '张四'), ('7', '', '2', '铁锤'), ('8', '', '2', '李三'), ('9', '', '2', '李一'), ('10', '', '2', '李二'), ('11', '', '2', '李四'), ('12', '', '3', '如花'), ('13', '', '3', '刘三'), ('14', '', '3', '刘一'), ('15', '', '3', '刘二'), ('16', '', '3', '刘四');
COMMIT;

-- ----------------------------
--  Table structure for `teacher`
-- ----------------------------
DROP TABLE IF EXISTS `teacher`;
CREATE TABLE `teacher` (
  `tid` int(11) NOT NULL AUTO_INCREMENT,
  `tname` varchar(32) NOT NULL,
  PRIMARY KEY (`tid`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `teacher`
-- ----------------------------
BEGIN;
INSERT INTO `teacher` VALUES ('1', '张磊老师'), ('2', '李平老师'), ('3', '刘海燕老师'), ('4', '朱云海老师'), ('5', '李杰老师');
COMMIT;

SET FOREIGN_KEY_CHECKS = 1;
数据库导出的文件

 

      首先咱们新建一个库:

      

      而后选择这个数据库,点击右键,选择运行sql文件;

      

      

      

      注意上面这一步,直接关闭就能够了,不要再次点击开始了

       

      而后经过ER图,来看看,各个表的关系就看的很清楚了。

      

      咱们还能够对sql语句进行注释:选中语句而后ctrl+/就能多行注释,ctrl+shift+/ 就能取消注释

      ok,Navicat简单的就介绍完了,你们能够练一练了~~~

 

MySQL数据备份

使用mysqldump实现逻辑备份

#语法:
# mysqldump -h 服务器 -u用户名 -p密码 数据库名 > 备份文件.sql

#示例:
#单库备份
mysqldump -uroot -p123 db1 > db1.sql
mysqldump -uroot -p123 db1 table1 table2 > db1-table1-table2.sql

#多库备份
mysqldump -uroot -p123 --databases db1 db2 mysql db3 > db1_db2_mysql_db3.sql

#备份全部库
mysqldump -uroot -p123 --all-databases > all.sql

恢复逻辑备份

#方法一:
[root@localhost backup]# mysql -uroot -p123 < /backup/all.sql

#方法二:
mysql> use db1;
mysql> SET SQL_LOG_BIN=0;
mysql> source /root/db1.sql

#注:若是备份/恢复单个库时,能够修改sql文件
DROP database if exists school;
create database school;
use school;

表的导出和导入

SELECT... INTO OUTFILE 导出文本文件
示例:
mysql> SELECT * FROM school.student1
INTO OUTFILE 'student1.txt'
FIELDS TERMINATED BY ',' //定义字段分隔符
OPTIONALLY ENCLOSED BY '' //定义字符串使用什么符号括起来
LINES TERMINATED BY '\n' ; //定义换行符


mysql 命令导出文本文件
示例:
# mysql -u root -p123 -e 'select * from student1.school' > /tmp/student1.txt
# mysql -u root -p123 --xml -e 'select * from student1.school' > /tmp/student1.xml
# mysql -u root -p123 --html -e 'select * from student1.school' > /tmp/student1.html

LOAD DATA INFILE 导入文本文件
mysql> DELETE FROM student1;
mysql> LOAD DATA INFILE '/tmp/student1.txt'
INTO TABLE school.student1
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY ''
LINES TERMINATED BY '\n';
#可能会报错
mysql> select * from db1.emp into outfile 'C:\\db1.emp.txt' fields terminated by ',' lines terminated by '\r\n';
ERROR 1238 (HY000): Variable 'secure_file_priv' is a read only variable


#数据库最关键的是数据,一旦数据库权限泄露,那么经过上述语句就能够轻松将数据导出到文件中而后下载拿走,于是mysql对此做了限制,只能将文件导出到指定目录
在配置文件中
[mysqld]
secure_file_priv='C:\\' #只能将数据导出到C:\\下

重启mysql
从新执行上述语句

数据库迁移

务必保证在相同版本之间迁移
# mysqldump -h 源IP -uroot -p123 --databases db1 | mysql -h 目标IP -uroot -p456

PyMySQL介绍

PyMySQL 是在 Python3.x 版本中用于链接 MySQL 服务器的一个库,Python2中则使用mysqldb。

Django中也可使用PyMySQL链接MySQL数据库。

PyMySQL安装

pip install pymysql

链接数据库

在进行本文如下内容以前须要注意:

  • 你有一个MySQL数据库,而且已经启动。
  • 你有能够链接该数据库的用户名和密码
  • 你有一个有权限操做的database

基本使用

 

import pymysql
user=input('用户名: ').strip()
pwd=input('密码: ').strip()

#连接,指定ip地址和端口,本机上测试时ip地址能够写localhost或者本身的ip地址或者127.0.0.1,而后你操做数据库的时候的用户名,密码,要指定你操做的是哪一个数据库,指定库名,还要指定字符集。否则会出现乱码
conn=pymysql.connect(host='localhost',port=3306,user='root',password='123',database='student',charset='utf8') #指定编码为utf8的时候,注意没有-,别写utf-8,数据库为
#获得conn这个链接对象
#游标
cursor=conn.cursor() #这就想到于mysql自带的那个客户端的游标mysql> 在这后面输入指令,回车执行
#cursor=conn.cursor(cursor=pymysql.cursors.DictCursor) #获取字典数据类型表示的结果:{'sid': 1, 'gender': '', 'class_id': 1, 'sname': '理解'} {'字段名':值}


#而后给游标输入sql语句并执行sql语句execute
sql='select * from userinfo where name="%s" and password="%s"' %(user,pwd) #注意%s须要加引号,执行这句sql的前提是医药有个userinfo表,里面有name和password两个字段,还有一些数据,本身添加数据昂
print(sql)
res=cursor.execute(sql) #执行sql语句,返回sql查询成功的记录数目,是个数字,是受sql语句影响到的记录行数,其实除了受影响的记录的条数以外,这些记录的数据也都返回了给游标,这个就至关于咱们subprocess模块里面的管道PIPE,乘放着返回的数据
#all_data=cursor.fetchall()  #获取返回的全部数据,注意凡是取数据,取过的数据就没有了,结果都是元祖格式的
#many_data=cursor.fetchmany(3) #一下取出3条数据,
#one_data=cursor.fetchone()  #按照数据的顺序,一次只拿一个数据,下次再去就从第二个取了,由于第一个被取出去了,取一次就没有了,结果也都是元祖格式的
  fetchone:(1, '', 1, '理解')
  fetchone:(2, '', 1, '钢蛋')
  fetchall:((3, '', 1, '张三'), (4, '', 1, '张一'))
#上面fetch的结果都是元祖格式的,无法看出哪一个数据是对应的哪一个字段,这样是否是不太好看,想想,咱们能够经过python的哪种数据类型,能把字段和对应的数据表示出来最清晰,固然是字典{'字段名':值}
#咱们能够再建立游标的时候,在cursor里面加上一个参数:cursor=conn.cursor(cursor=pymysql.cursors.DictCursor)获取的结果就是字典格式的,fetchall或者fetchmany取出的结果是列表套字典的数据形式


上面咱们说,咱们的数据取一次是否是就没有了啊,实际上不是的,这个取数据的操做就像读取文件内容同样,每次read以后,光标就移动到了对应的位置,咱们能够经过seek来移动光标
一样,咱们能够移动游标的位置,继续取咱们前面的数据,经过cursor.scroll(数字,模式),第一个参数就是一个int类型的数字,表示日后移动的记录条数,第二个参数为移动的模式,有两个值:absolute:绝对移动,relative:相对移动
#绝对移动:它是相对于全部数据的起始位置开始日后面移动的
#相对移动:他是相对于游标的当前位置开始日后移动的

#绝对移动的演示
#print(cursor.fetchall())
#cursor.scroll(3,'absolute') #从初始位置日后移动三条,那么下次取出的数据为第四条数据
#print(cursor.fetchone())

#相对移动的演示
#print(cursor.fetchone())
#cursor.scroll(1,'relative') #经过上面取了一次数据,游标的位置在第二条的开头,我如今相对移动了1个记录,那么下次再取,取出的是第三条,我相对于上一条,往下移动了一条
#print(cursor.fetchone())

print(res) #一个数字

cursor.close() #关闭游标
conn.close()   #关闭链接

if res:
    print('登陆成功')
else:
    print('登陆失败')

 

注意事项

charset=“utf8”,编码不要写成"utf-8"

 

3. SQL注入问题
1. 什么是SQL注入?
用户输入的内容有恶意的SQL语句,后端拿到用户输入的内容不作检测直接作字符串拼接,获得一个和预期不一致的SQL语句
2. 如何解决SQL注入?
对用户输入的内容作检测
pymysql内置了这种检测,咱们只须要让pymysql帮咱们拼接sql语句
ret = cursor.execute(sql, [name, pwd]) # 让pymysql模块帮咱们拼接sql语句,执行SQL语句

好比:

uname = input('请输入用户名:')
pword = input('请输入密码:')

sql = "select * from userinfo where username='%s' and password='%s';"%(uname,pword)
print(sql)
res = cursor.execute(sql) #res咱们说是获得的行数,若是这个行数不为零,说明用户输入的用户名和密码存在,若是为0说名存在,你想一想对不

print(res) #若是输入的用户名和密码错误,这个结果为0,若是正确,这个结果为1
if res:
    print('登录成功')
else:
    print('用户名和密码错误!')
#运行看结果:竟然登录成功
请输入用户名:chao' -- xxx
请输入密码:
select * from userinfo where username='chao' -- xxx' and password='';
登录成功

咱们来分析一下:
此时uname这个变量等于什么,等于chao' -- xxx,而后咱们来看咱们的sql语句被这个字符串替换以后是个什么样子:
select * from userinfo where username='chao' -- xxx' and password=''; 其中chao后面的这个',在进行字符串替换的时候,咱们输入的是chao',这个引号和前面的引号组成了一对,而后后面--在sql语句里面是注释的意思,也就是说--后面的sql语句被注释掉了。也就是说,拿到的sql语句是select * from userinfo where username='chao';而后就去本身的数据库里面去执行了,发现可以找到对应的记录,由于有用户名为chao的记录,而后他就登录成功了,可是其实他连密码都不知道,只知道个用户名。。。,他完美的跳过了你的认证环节。

而后咱们再来看一个例子,直接连用户名和密码都不知道,可是依然可以登录成功的状况

请输入用户名:xxx' or 1=1 -- xxxxxx
请输入密码:
select * from userinfo where username='xxx' or 1=1 -- xxxxxx' and password='';
登录成功

咱们只输入了一个xxx' 加or 加 1=1 加 -- 加任意字符串
看上面被执行的sql语句你就发现了,or 后面跟了一个永远为真的条件,那么即使是username对不上,可是or后面的条件是成立的,也可以登录成功。
总结我们刚才说的两种sql注入的语句
#一、sql注入之:用户存在,绕过密码 chao' -- 任意字符 #二、sql注入之:用户不存在,绕过用户与密码 xxx' or 1=1 -- 任意字符
解决方法总结:
# 原来是咱们对sql进行字符串拼接
# sql="select * from userinfo where name='%s' and password='%s'" %(user,pwd)
# print(sql)
# res=cursor.execute(sql)

#改写为(execute帮咱们作字符串拼接,咱们无需且必定不能再为%s加引号了)
sql="select * from userinfo where name=%s and password=%s" #!!!注意%s须要去掉引号,由于pymysql会自动为咱们加上
res=cursor.execute(sql,[user,pwd]) #pymysql模块自动帮咱们解决sql注入的问题,只要咱们按照pymysql的规矩来。

增删改查操做

import pymysql


# 1. 链接数据库,获得一个链接
conn = pymysql.connect(
    host='192.168.16.94',
    port=3306,
    user='bbn',
    # password='123',
    database='day43',
    charset='utf8'
)
# 2. 获取光标
cursor = conn.cursor()
# 3. 执行SQL语句
# 3.1 获得SQL语句
sql = "insert into userinfo(username, password) values (%s,%s);"  # 按照pymysql模块的写法定义好占位符
# 3.2 使用光标对象执行SQL语句
ret = cursor.execute(sql, ['Eva_J', '456'])  # 让pymysql模块帮咱们拼接sql语句,执行SQL语句
# 涉及操做数据库的 必定要提交
conn.commit()
# 关闭
cursor.close()
conn.close()

批量执行

# 导入pymysql模块
import pymysql
# 链接database
conn = pymysql.connect(host=“你的数据库地址”, user=“用户名”,password=“密码”,database=“数据库名”,charset=“utf8”)
# 获得一个能够执行SQL语句的光标对象
cursor = conn.cursor()
sql = "INSERT INTO USER1(name, age) VALUES (%s, %s);"
data = [("Alex", 18), ("Egon", 20), ("Yuan", 21)]
try:
    # 批量执行多条插入SQL语句
    cursor.executemany(sql, data)
    # 提交事务
    conn.commit()
except Exception as e:
    # 有异常,回滚事务
    conn.rollback()
cursor.close()
conn.close()

 

import pymysql


# 1. 链接数据库,获得一个链接
conn = pymysql.connect(
    host='192.168.16.94',
    port=3306,
    user='bbn',
    # password='123',
    database='day43',
    charset='utf8'
)
# 2. 获取光标
cursor = conn.cursor()
# 3. 执行SQL语句
# 3.1 获得SQL语句
sql = "delete from userinfo where username=%s;"  # 按照pymysql模块的写法定义好占位符
# 3.2 使用光标对象执行SQL语句
ret = cursor.execute(sql, ['alex'])  # 让pymysql模块帮咱们拼接sql语句,执行SQL语句
# 涉及操做数据库的 必定要提交
conn.commit()
# 关闭
cursor.close()
conn.close()

import pymysql


# 1. 链接数据库,获得一个链接
conn = pymysql.connect(
    host='192.168.16.94',
    port=3306,
    user='bbn',
    # password='123',
    database='day43',
    charset='utf8'
)
# 2. 获取光标
cursor = conn.cursor()
# 3. 执行SQL语句
# 3.1 获得SQL语句
sql = "update userinfo set password=%s where username=%s;"  # 按照pymysql模块的写法定义好占位符
# 3.2 使用光标对象执行SQL语句
ret = cursor.execute(sql, ['789', 'gold'])  # 让pymysql模块帮咱们拼接sql语句,执行SQL语句
# 涉及操做数据库的 必定要提交
conn.commit()
# 关闭
cursor.close()
conn.close()

取刚才插入到数据库的id值,插入数据失败回滚

# 导入pymysql模块
import pymysql
# 链接database
conn = pymysql.connect(host=“你的数据库地址”, user=“用户名”,password=“密码”,database=“数据库名”,charset=“utf8”)
# 获得一个能够执行SQL语句的光标对象
cursor = conn.cursor()
sql = "INSERT INTO USER1(name, age) VALUES (%s, %s);"
username = "Alex"
age = 18
try:
    # 执行SQL语句
    cursor.execute(sql, [username, age])
    # 提交事务
    conn.commit()
    # 提交以后,获取刚插入的数据的ID
    last_id = cursor.lastrowid
except Exception as e:
    # 有异常,回滚事务
    conn.rollback()
cursor.close()
conn.close()
相关文章
相关标签/搜索