Million annual salary python road - MySQL database Navicat tool of the module and pymysql

A. IDE tool introduced (Navicat)

Production environment is recommended to use the mysql command line, but for the convenience of our tests, you can use the IDE tools, we use Navicat tool, this tool is essentially a socket client, visualization of a tool to connect mysql server, and he is a graphical interface version of. We use it directly on the command line using the difference between a similar difference between linux and windows operating system up.

Download link: https: //pan.baidu.com/s/1bpo5mqj

Navicat installation tutorial reading this blog: https://www.cnblogs.com/clschao/articles/10022040.html

掌握:
    # 1. 测试+链接数据库
    # 2. 新建库
    # 3. 新建表,新建字段+类型+约束
    # 4. 设计表: 外键
    # 5. 新建查询
    # 6. 备份库/表
    
    
# 注意:
批量加注释: ctrl + ? 键
批量去注释: ctrl + shift + ? 键

Two. Pymysql module

1. pymysql installation

# 安装
一:
    pip3 install pymysql
二:
    PyCharm里settings-----> Project Interpreter-----> 右上角的加号+  ------> 搜索框里搜索

2. python database connection

import pymysql

# 打开数据库连接
conn = pymysql.connect('数据库ip','用户账号','密码','数据库名')  

# 使用 cursor() 方法创建一个游标对象 cursor
cursor = conn.cursor()

# 使用 execute() 方法执行 SQL语句
cursor.execute("SQL语句")

# 查询
data = cursor.fetchone()    # 查询单行数据
data = cursor.fetchmany(条数) # 查询多行数据
data = cursor.fetchall()    # 查询所有的数据
print(data)

# 关闭游标
cursor.close()

# 关闭数据库连接
conn.close()

More parameters

import pymysql

conn = pymysql.connect(
        host='localhost', user='root', password="123",
        database='db', port=3306, charset='utf8',   # charset时utf8,不能是utf-8
)

cur = conn.cursor(cursor=pymysql.cursors.DictCursor)    # 可以把cursor得到的结果集变成[{},{},......]这种列表里套字典形式.fetchall或者fetchmany取出的结果是列表套字典的数据形式,如果fetchmany(1)则取到的结果是一个字典,而不是列表套字典

3. The lookup table operation

Python Mysql query using either fetchone () method to obtain a single data used or fetchall () method to obtain a plurality of data.

  • fetchone (): This method acquires a next query result set. The result set is a target
  • fetchall (): receive all results returned rows.
  • rowcount: This read-only attribute, and return execution execute () method of the number of rows affected.
import pymysql

# 建立数据库连接,第一个参数:ip地址,第二个:用户名,第三个:密码,第四个:数据库名
conn = pymysql.connect('127.0.0.1','root','123456','pysql')

# 使用cursor()方法创建一个游标对象 cursor 
# cursor = conn.cursor()
cur = conn.cursor(cursor=pymysql.cursors.DictCursor)

# sql代码
sql = 'select * from info;'

# 执行sql语句,返回sql查询成功的记录数目,是个数字,是受sql语句影响到的记录行数,其实除了受影响的记录的条数之外,这些记录的数据也都返回了给游标
row = cursor.execute(sql)

print(cursor.rowcount)  # 这是一个只读属性,并返回执行execute()方法后影响的行数
print(row)  # 一个数字

# one_data = cursor.fetchone()
# many_data = cursor.fetchmany(3)   # 当括号里写1是,得到的是字典
# all_data = cursor.fetchall()

# print(one_data)
# print(many_data)
# print(all_data)

cursor.close()  # 关闭游标
conn.close()    # 关闭连接
Cursor movement
我们可以移动游标的位置,继续取我们前面的数据,通过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())

4. Operation additions and deletions to the data

Be sure to database connection object .commit () submission, or the database does not change.

Insert data
import pymysql
 
# 打开数据库连接
conn = pymysql.connect('127.0.0.1','root','123456','pysql')
 
# 使用cursor()方法获取操作游标 
cursor = conn.cursor()
 
# SQL 插入语句
sql = """ insert into info(username,password) values('zfy','123456'),('lfz','123');"""

try:
   cursor.execute(sql) # 执行sql语句
   conn.commit()         # 提交到数据库执行
except:
   conn.rollback()       # 如果发生错误则回滚
 
# 关闭数据库连接
conn.close()
delete data
import pymysql
 
# 打开数据库连接
conn = pymysql.connect('127.0.0.1','root','123456','pysql')
 
# 使用cursor()方法获取操作游标 
cursor = conn.cursor()
 
# SQL 删除语句
sql = """ delete from info where id = %s""" # 不要直接字符串拼接,防止sql注入

try:
   cursor.execute(sql,[2]) # 执行sql语句,第二个参数:列表里写sql的拼接字符.
   conn.commit()         # 提交到数据库执行
except:
   conn.rollback()       # 如果发生错误则回滚
 
# 关闭数据库连接
conn.close()
update data
import pymysql
 
# 打开数据库连接
conn = pymysql.connect('127.0.0.1','root','123456','pysql')
 
# 使用cursor()方法获取操作游标 
cursor = conn.cursor()
 
# SQL 更新语句
sql = """ update info set password = 'hahaha' where id = %s """ # 不要直接字符串拼接,防止sql注入

try:
   cursor.execute(sql,[3]) # 执行sql语句,第二个参数:列表里写sql的拼接字符.
   conn.commit()         # 提交到数据库执行
except:
   conn.rollback()       # 如果发生错误则回滚
 
# 关闭数据库连接
conn.close()

4. Get the last data of the inserted self-energizing ID

import pymysql
conn=pymysql.connect(host='localhost',user='root',password='123',database='egon')
cursor=conn.cursor()

sql='insert into userinfo(name,password) values("xxx","123");'
rows=cursor.execute(sql)
print(cursor.lastrowid) #在插入语句后查看

conn.commit()

cursor.close()
conn.close()

5. execute () of injection sql

Before we username password authentication is first saved to a file in the user name and password, and then sent over to the client, and by reading the contents of a file inside the username and password match, and now we learn the database, we can save user data into a database, and then authenticates the user name and password for client data inside the database.

Create a user information table userinfo itself, which contains two fields, username, and password, and then write the two records which

    img

#我们来使用数据来进行一下用户名和密码的认证操作
import pymysql

conn = pymysql.connect(
    host='127.0.0.1',
    port=3306,
    user='root',
    password='666',
    database='crm',
    charset='utf8'
)

cursor = conn.cursor(pymysql.cursors.DictCursor)
uname = input('请输入用户名:')
pword = input('请输入密码:')

sql = "select * from userinfo where username='%s' and password='%s';"%(uname,pword)

res = cursor.execute(sql) #res我们说是得到的行数,如果这个行数不为零,说明用户输入的用户名和密码存在,如果为0说名存在,你想想对不

print(res) #如果输入的用户名和密码错误,这个结果为0,如果正确,这个结果为1
if res:
    print('登陆成功')
else:
    print('用户名和密码错误!')

#通过上面的验证方式,比我们使用文件来保存用户名和密码信息的来进行验证操作要方便很多。

But we look at the following operations, if the input chao in a place to enter a user name 'box and then - and then add a space arbitrary strings, will be able to log in successfully, that is, only knowing the user's name, he You will be able to log in case of success:

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='';
1
登陆成功

我们来分析一下:
此时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的记录,然后他就登陆成功了,但是其实他连密码都不知道,只知道个用户名。。。,他完美的跳过了你的认证环节。

Then we look at an example, once a user name and password directly do not know, but still be able to log in is successful:

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

我们只输入了一个xxx' 加or 加 1=1 加 -- 加任意字符串
看上面被执行的sql语句你就发现了,or 后面跟了一个永远为真的条件,那么即便是username对不上,但是or后面的条件是成立的,也能够登陆成功。

The above two examples are two problems sql injection, read the two examples above, there is no feeling back cold ah Comrades, do not worry, we have to solve this problem, how to solve it?

Some sites directly when you enter the content, is not it give you a limited, you can not enter some special symbols, as some special symbols can change the execution logic sql, in fact, not only is - there are other symbols also change the execution logic sql statements, we are in this program to place the client user input restrictions, but others can you simulate your client sends a request, it is possible, he impersonate a client, you do not follow the client's requirements, we made some special characters, your client is not limited. So was this a simple filter special characters can not solve the fundamental problem of the client, how to do? We also need to verify that the server can be matched by the special character of the content is to be sent by the client, if you have these special characters, we just let it failed on landing.

    In the service side to solve the problem sql injection: Do not own to carry out the splicing sql string, pymysql help us stitching, he was able to prevent sql injection, so after we write sql statement when written in the following way:

之前我们的sql语句是这样写的:
sql = "select * from userinfo where username='%s' and password='%s';"%(uname,pword)

以后再写的时候,sql语句里面的%s左右的引号去掉,并且语句后面的%(uname,pword)这些内容也不要自己写了,按照下面的方式写
sql = "select * from userinfo where username=%s and password=%s;"
难道我们不传值了吗,不是的,我们通过下面的形式,在excute里面写参数:
#cursor.execute(sql,[uname,pword]) ,其实它本质也是帮你进行了字符串的替换,只不过它会将uname和pword里面的特殊字符给过滤掉。

看下面的例子:
uname = input('请输入用户名:') #输入的内容是:chao' -- xxx或者xxx' or 1=1 -- xxxxx
pword = input('请输入密码:')

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

print(res) #如果输入的用户名和密码错误,这个结果为0,如果正确,这个结果为1
if res:
    print('登陆成功')
else:
    print('用户名和密码错误!')
#看结果:
请输入用户名:xxx' or 1=1 -- xxxxx
请输入密码:
select * from userinfo where username=%s and password=%s;
0
用户名和密码错误!

excute by pymysql provide the perfect solution to the problem.

总结咱们刚才说的两种sql注入的语句
#1、sql注入之:用户存在,绕过密码
chao' -- 任意字符

#2、sql注入之:用户不存在,绕过用户与密码
xxx' or 1=1 -- 任意字符

Solution Summary:

# 原来是我们对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的规矩来。

Guess you like

Origin www.cnblogs.com/zhangchaoyin/p/11454818.html