目录
关于 sql 注入
用户存在, 绕过密码
用户不存在, 绕过用户与密码
解决 sql 注入问题
commit()
增
改
删
查询数据库
- fetchone()
- fetchall()
- fetchmany()
补充:
建立链接时间过长后会自动断开链接, 可像下面这样解决:
conn.ping(reconnect=True)
检查链接是否还存在, 参数 reconnect=True 表示如果链接已不存在, 则重新建立链接
补充:
- # 回滚, 通常用于事务
- conn.rollback()
pymysql 模块用于在 Python 程序中操作数据库.
该模块本质是一个套接字客户端软件.
Windows 安装命令: pip3 install pymysql
基本使用:
- # 准备数据库, 数据和远程用户:
- MySQL> select * from blog.userinfo;
- +----+------+-----+
- | id | name | pwd |
- +----+------+-----+
- | 1 | zyk | ___ |
- +----+------+-----+
- 1 row in set (0.00 sec)
- MySQL> show grants for 'zyk'@'%';
- +------------------------------------------+
- | Grants for [email protected]% |
- +------------------------------------------+
- | GRANT ALL PRIVILEGES ON *.* TO 'zyk'@'%' |
- +------------------------------------------+
- 1 row in set (0.00 sec)
- # 实现: 使用 Python 程序实现用户登陆, 如果用户存在则登陆成功
- import pymysql
- user, pwd = input('user:'), input('pwd:')
- # 1. 连接数据库
- conn = pymysql.connect(
- host='127.0.0.1',
- port=3306,
- user='zyk',
- password='[email protected]',
- db='blog', # 要连接的数据库名称
- charset='utf8' # 要连接的数据库编码
- )
- # 2. 创建游标
- cursor = conn.cursor()
- # 3. 执行 sql 语句
- sql = "select name,pwd from userinfo where name='%s'and pwd='%s'" % (user, pwd)
- result = cursor.execute(sql) # 返回 sql 查询成功的记录数目 (查到一条数据后便停止查询)
- # print(result) # 即: 成功返回 1, 否则 0
- # 4. 关闭
- cursor.close() # 关闭游标
- conn.close() # 关闭连接
- print('log in successfully!') if result else print('logon failure!')
关于 sql 注入
补充: 最新版本的 pymysql 已经不能 sql 注入了, 只要加了 "--" 就会报错.
用户存在, 绕过密码
利用 sql 语句中的注释 (--), 注释掉密码的部分.
- import pymysql
- user, pwd = input('user:'), input('pwd:')
- # 1. 连接数据库
- conn = pymysql.connect(
- host='127.0.0.1',
- port=3306,
- user='zyk',
- password='[email protected]',
- db='blog', # 要连接的数据库名称
- charset='utf8' # 要连接的数据库编码
- )
- # 2. 创建游标
- cursor = conn.cursor()
- # 3. 执行 sql 语句
- # sql = "select name,pwd from userinfo where name='%s'and pwd='%s'" % (user, pwd)
- # 用户存在, 绕过密码
- sql = "select name,pwd from userinfo where name='%s'-- abc' and pwd='%s'" % (user, pwd) # 注意:-- 后面要有一个空格,'abc'为任意字符, 后面还要加个单引号
- print(sql)
- result = cursor.execute(sql) # 返回 sql 查询成功的记录数目
- # print(result) # 即: 成功返回 1, 否则 0
- # 4. 关闭
- cursor.close() # 关闭游标
- conn.close() # 关闭连接
- print('log in successfully!') if result else print('logon failure!')
- """
- 代码输出如下:
- user:zyk
- pwd:
- select name,pwd from userinfo where name='zyk' -- abc'and pwd=''
- log in successfully!
- """
可见, 我们只输入了用户名, 并没有输入密码 (密码被注释掉了), 依然显示登陆成功.
用户不存在, 绕过用户与密码
利用 or 语法, 添加一条结果为 True 的语句, 并注释掉密码的部分.
- import pymysql
- user, pwd = input('user:'), input('pwd:')
- # 1. 连接数据库
- conn = pymysql.connect(
- host='127.0.0.1',
- port=3306,
- user='zyk',
- password='[email protected]',
- db='blog', # 要连接的数据库名称
- charset='utf8' # 要连接的数据库编码
- )
- # 2. 创建游标
- cursor = conn.cursor()
- # 3. 执行 sql 语句
- # sql = "select name,pwd from userinfo where name='%s'and pwd='%s'" % (user, pwd)
- # 用户不存在, 绕过用户与密码
- sql = "select name,pwd from userinfo where name='%s'or 1=1 -- abc' and pwd='%s'" % (user, pwd)
- print(sql)
- result = cursor.execute(sql) # 返回 sql 查询成功的记录数目
- # print(result) # 即: 成功返回 1, 否则 0
- # 4. 关闭
- cursor.close() # 关闭游标
- conn.close() # 关闭连接
- print('log in successfully!') if result else print('logon failure!')
- """
- 代码输出如下:
- user:
- pwd:
- select name,pwd from userinfo where name=''or 1=1 -- abc' and pwd=''
- log in successfully!
- """
可见, 我们并为输入用户名和密码, 依然显示登陆成功.
解决 sql 注入问题
pymysql 模块自带解决 sql 注入的问题, 只要我们按照 pymysql 模块的规定就行.
- import pymysql
- user, pwd = input('user:'), input('pwd:')
- # 1. 连接数据库
- conn = pymysql.connect(
- host='127.0.0.1',
- port=3306,
- user='zyk',
- password='[email protected]',
- db='blog', # 要连接的数据库名称
- charset='utf8' # 要连接的数据库编码
- )
- # 2. 创建游标
- cursor = conn.cursor()
- # 3. 执行 sql 语句
- # sql = "select name,pwd from userinfo where name='%s'and pwd='%s'" % (user, pwd)
- # result = cursor.execute(sql) # 返回 sql 查询成功的记录数目
- # print(result) # 即: 成功返回 1, 否则 0
- # 改写为 (execute 帮我们拼接字符串, 我们无需且一定不能再为 %s 加引号)
- sql = 'select name,pwd from userinfo where name=%s and pwd=%s'
- # 改写为 (用 agrs 参数传入用户名及密码)
- result = cursor.execute(sql, [user, pwd])
- # 4. 关闭
- cursor.close() # 关闭游标
- conn.close() # 关闭连接
- print('log in successfully!') if result else print('logon failure!')
execute 的 arges 参数可以接受 list,tuple 或 dict:
如果 args 是一个列表或元组,%s 可以用作查询中的占位符.
如果 args 是一个 dict, %(name)s 可以用作查询中的占位符.
- # arges 参数为 dict 时的写法:
- sql = 'select name,pwd from userinfo where name=%(name)s and pwd=%(pwd)s'
- result = cursor.execute(sql, {
- 'name': user, 'pwd': pwd
- })
- commit()
在数据库里增, 删, 改, 只是在内存中操作, 所以必须要进行提交, 否则插入的数据不但不会生效, 还会影响到自增 id.
增
- import pymysql
- user, pwd = input('user:'), input('pwd:')
- conn = pymysql.connect(
- host='127.0.0.1',
- port=3306,
- user='zyk',
- password='[email protected]',
- db='blog', # 要连接的数据库名称
- charset='utf8' # 要连接的数据库编码
- )
- # 创建游标
- cursor = conn.cursor()
- # 增
- sql = 'insert into userinfo(name, pwd) values (%s, %s)'
- effect_row = cursor.execute(sql,(user, pwd))
- print(effect_row) # 返回增加的记录数
- # 同时插入多条数据: executemany()
- # effect_row = cursor.executemany(sql, [("张三", '123'), ("李四", '456')])
- # 一定要记得提交
- conn.commit()
- # 关闭
- cursor.close()
- conn.close()
改
- import pymysql
- new_name = input('>>>')
- conn = pymysql.connect(
- host='127.0.0.1',
- port=3306,
- user='zyk',
- password='[email protected]',
- db='blog', # 要连接的数据库名称
- charset='utf8' # 要连接的数据库编码
- )
- # 创建游标
- cursor = conn.cursor()
- # 改
- sql = "update userinfo set name=%s where name='zyk'"
- effect_row = cursor.execute(sql, new_name)
- print(effect_row) # 返回修改的记录数
- # 一定要记得提交
- conn.commit()
- # 关闭
- cursor.close()
- conn.close()
删
- import pymysql
- conn = pymysql.connect(
- host='127.0.0.1',
- port=3306,
- user='zyk',
- password='[email protected]',
- db='blog', # 要连接的数据库名称
- charset='utf8' # 要连接的数据库编码
- )
- cursor = conn.cursor()
- # 删
- sql = "delete from userinfo where name='张三'or name='李四'" # 同时删除多条记录
- effect_row = cursor.execute(sql)
- print(effect_row) # 返回删除的记录数
- # 一定要记得提交
- conn.commit()
- # 关闭
- cursor.close()
- conn.close()
查询数据库
- fetchone() # 获取下一行数据, 第一次为首行
- fetchall() # 获取所有行数据
- fetchmany(4) # 获取 4 行数
表内容如下:
![在这里插入图片描述](http://blog.gqylpy.com/media/ai/2019-03/a9d04dbf-2fee-42ac-89e3-4668738730c0.png)
- fetchone()
- import pymysql
- # 连接数据库
- conn = pymysql.connect(
- host='localhost',
- port=3306,
- user='zyk',
- password='[email protected]',
- db='blog',
- charset='utf8'
- )
- # 创建游标
- cursor = conn.cursor()
- # 执行 sql 语句
- sql = 'select * from userinfo'
- cursor.execute(sql)
- # 查询第一行数据
- row = cursor.fetchone()
- print(row)
- # 查询第二行数据
- row = cursor.fetchone()
- print(row)
- # 关闭
- cursor.close()
- conn.close()
- """
- 输出:
- (1, 'zyk', '___')
- (2, '张三', '123')
- """
如上: 在获取行数据的时候, 可以理解为开始. 有一个行指针指向第一行, 获取一行, 他就向下移动一行. 所以当行指针移动到最后一行时, 便无法在获取到数据了 (None). 此时我们可以使用如下方法来移动行指针:
- cursor.scroll(1, mode='relative') # 相对当前位置移动
- cursor.scroll(2, mode='absolute') # 相对绝对位置移动
值 1 为移动的行数, relative: 可指定负数 (向上移动);adsolute:0 为第一行;
mode 指定的是相对于当前行移动还是? 相对于首行移动.??????
- fetchall()
- import pymysql
- # 连接数据库
- conn = pymysql.connect(
- host='localhost',
- port=3306,
- user='zyk',
- password='[email protected]',
- db='blog',
- charset='utf8'
- )
- # 创建游标
- cursor = conn.cursor()
- # 执行 sql 语句
- sql = 'select * from userinfo'
- cursor.execute(sql)
- # 获取所有数据
- rows = cursor.fetchall()
- print(rows)
- # 关闭
- cursor.close()
- conn.close()
- """
- 输出:
- ((1, 'zyk', '___'), (2, '张三', '123'), (3, '李四', '456'))
- """
默认情况下, 我们获取到的返回值是元组, 可使用以下方式来返回字典:
- # 在实例化时, 将属性 cursor 设置为:
- cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
- fetchmany()
- import pymysql
- # 连接数据库
- conn = pymysql.connect(
- host='localhost',
- port=3306,
- user='zyk',
- password='[email protected]',
- db='blog',
- charset='utf8'
- )
- # 创建游标
- cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
- # 执行 sql 语句
- sql = 'select * from userinfo'
- cursor.execute(sql)
- # 获取 2 条数据
- rows = cursor.fetchmany(2)
- print(rows)
- # 如果此时想要再获取已经获取过的数据, 就需要移动行指针
- cursor.scroll(0, mode='absolute') # 移动到第一行
- rows = cursor.fetchall()
- print(rows)
- # 关闭
- cursor.close()
- conn.close()
- """
- 输出:
- [{'id': 1, 'name': 'zyk', 'pwd': '___'}, {'id': 2, 'name': '张三', 'pwd': '123'}]
- [{'id': 1, 'name': 'zyk', 'pwd': '___'}, {'id': 2, 'name': '张三', 'pwd': '123'}, {'id': 3, 'name': '李四', 'pwd': '456'}]
- """
人生中不可避免的定律
定律一: 财富定律
勤劳不一定能够致富, 但懒惰一定不能致富.
定律二: 忙碌定律
人可以为了自己的梦想而去忙碌, 但不能因为你忙碌而失去梦想.
定律三: 担心定律
你越是担心的事情越有可能发生.
定律四: 执着定律
任何的事情都不可过分执着, 无论是风光还是难堪这些都会过去.
定律五: 堵住定律
有很多越是输不起的人, 越是喜欢下大赌注.
定律六: 目标定律
目标太多, 最后只会是失去目标, 知道自己想要什么的人, 能比都想要的人更容易成功.
定律七: 方向定律
如果一个人不知道自己要向往哪个码头, 那么不管什么风都不会是顺风.
定律八: 诱惑定律
凡是抵挡不住诱惑的人, 十之八九是没有经历过诱惑的人, 这与诱惑大小无关.
定律九: 时间定律
时间就是生命, 对于男人来说是积累, 对于女人来说是消耗.
年轻本无价, 一身碌碌无为
让无价变为了低价, 你应该珍惜自己的机会.
来源: http://www.bubuko.com/infodetail-3158906.html