"

目录

关于sql注入

用户存在,绕过密码

用户不存在,绕过用户与密码

解决sql注入问题

commit()

查询数据库

fetchone()

fetchall()

fetchmany()

补充:

建立链接时间过长后会自动断开链接,可像下面这样解决:

conn.ping(reconnect=True)

检查链接是否还存在,参数reconnect=True 表示如果链接已不存在,则重新建立链接


补充:


  1. # 回滚,通常用于事务
  2. conn.rollback()

pymysql模块用于在Python程序中操作数据库.

该模块本质是一个套接字客户端软件.


Windows安装命令:pip3 install pymysql

基本使用:


  1. # 准备数据库、数据和远程用户:
  2. mysql> select * from blog.userinfo;
  3. +----+------+-----+
  4. | id | name | pwd |
  5. +----+------+-----+
  6. | 1 | zyk | ___ |
  7. +----+------+-----+
  8. 1 row in set (0.00 sec)
  9. mysql> show grants for 'zyk'@'%';
  10. +------------------------------------------+
  11. | Grants for zyk@% |
  12. +------------------------------------------+
  13. | GRANT ALL PRIVILEGES ON *.* TO 'zyk'@'%' |
  14. +------------------------------------------+
  15. 1 row in set (0.00 sec)

  1. # 实现:使用Python程序实现用户登陆,如果用户存在则登陆成功
  2. import pymysql
  3. user, pwd = input('user:'), input('pwd:')
  4. # 1. 连接数据库
  5. conn = pymysql.connect(
  6. host='127.0.0.1',
  7. port=3306,
  8. user='zyk',
  9. password='user@zyk',
  10. db='blog', # 要连接的数据库名称
  11. charset='utf8' # 要连接的数据库编码
  12. )
  13. # 2. 创建游标
  14. cursor = conn.cursor()
  15. # 3. 执行sql语句
  16. sql = "select name,pwd from userinfo where name='%s' and pwd='%s'" % (user, pwd)
  17. result = cursor.execute(sql) # 返回sql查询成功的记录数目(查到一条数据后便停止查询)
  18. # print(result) # 即:成功返回1,否则0
  19. # 4. 关闭
  20. cursor.close() # 关闭游标
  21. conn.close() # 关闭连接
  22. print('log in successfully!') if result else print('logon failure!')

关于sql注入

补充:最新版本的pymysql已经不能sql注入了,只要加了 "--" 就会报错.

用户存在,绕过密码

利用sql语句中的注释(--),注释掉密码的部分.


  1. import pymysql
  2. user, pwd = input('user:'), input('pwd:')
  3. # 1. 连接数据库
  4. conn = pymysql.connect(
  5. host='127.0.0.1',
  6. port=3306,
  7. user='zyk',
  8. password='user@zyk',
  9. db='blog', # 要连接的数据库名称
  10. charset='utf8' # 要连接的数据库编码
  11. )
  12. # 2. 创建游标
  13. cursor = conn.cursor()
  14. # 3. 执行sql语句
  15. # sql = "select name,pwd from userinfo where name='%s' and pwd='%s'" % (user, pwd)
  16. # 用户存在,绕过密码
  17. sql = "select name,pwd from userinfo where name='%s' -- abc' and pwd='%s'" % (user, pwd) # 注意:--后面要有一个空格,'abc'为任意字符,后面还要加个单引号
  18. print(sql)
  19. result = cursor.execute(sql) # 返回sql查询成功的记录数目
  20. # print(result) # 即:成功返回1,否则0
  21. # 4. 关闭
  22. cursor.close() # 关闭游标
  23. conn.close() # 关闭连接
  24. print('log in successfully!') if result else print('logon failure!')
  25. """
  26. 代码输出如下:
  27. user:zyk
  28. pwd:
  29. select name,pwd from userinfo where name='zyk' -- abc' and pwd=''
  30. log in successfully!
  31. """

可见,我们只输入了用户名,并没有输入密码(密码被注释掉了),依然显示登陆成功.

用户不存在,绕过用户与密码

利用or语法,添加一条结果为True的语句,并注释掉密码的部分.


  1. import pymysql
  2. user, pwd = input('user:'), input('pwd:')
  3. # 1. 连接数据库
  4. conn = pymysql.connect(
  5. host='127.0.0.1',
  6. port=3306,
  7. user='zyk',
  8. password='user@zyk',
  9. db='blog', # 要连接的数据库名称
  10. charset='utf8' # 要连接的数据库编码
  11. )
  12. # 2. 创建游标
  13. cursor = conn.cursor()
  14. # 3. 执行sql语句
  15. # sql = "select name,pwd from userinfo where name='%s' and pwd='%s'" % (user, pwd)
  16. # 用户不存在,绕过用户与密码
  17. sql = "select name,pwd from userinfo where name='%s' or 1=1 -- abc' and pwd='%s'" % (user, pwd)
  18. print(sql)
  19. result = cursor.execute(sql) # 返回sql查询成功的记录数目
  20. # print(result) # 即:成功返回1,否则0
  21. # 4. 关闭
  22. cursor.close() # 关闭游标
  23. conn.close() # 关闭连接
  24. print('log in successfully!') if result else print('logon failure!')
  25. """
  26. 代码输出如下:
  27. user:
  28. pwd:
  29. select name,pwd from userinfo where name='' or 1=1 -- abc' and pwd=''
  30. log in successfully!
  31. """

可见,我们并为输入用户名和密码,依然显示登陆成功.

解决sql注入问题

pymysql模块自带解决sql注入的问题,只要我们按照pymysql模块的规定就行.


  1. import pymysql
  2. user, pwd = input('user:'), input('pwd:')
  3. # 1. 连接数据库
  4. conn = pymysql.connect(
  5. host='127.0.0.1',
  6. port=3306,
  7. user='zyk',
  8. password='user@zyk',
  9. db='blog', # 要连接的数据库名称
  10. charset='utf8' # 要连接的数据库编码
  11. )
  12. # 2. 创建游标
  13. cursor = conn.cursor()
  14. # 3. 执行sql语句
  15. # sql = "select name,pwd from userinfo where name='%s' and pwd='%s'" % (user, pwd)
  16. # result = cursor.execute(sql) # 返回sql查询成功的记录数目
  17. # print(result) # 即:成功返回1,否则0
  18. # 改写为(execute帮我们拼接字符串,我们无需且一定不能再为%s加引号)
  19. sql = 'select name,pwd from userinfo where name=%s and pwd=%s'
  20. # 改写为(用agrs参数传入用户名及密码)
  21. result = cursor.execute(sql, [user, pwd])
  22. # 4. 关闭
  23. cursor.close() # 关闭游标
  24. conn.close() # 关闭连接
  25. print('log in successfully!') if result else print('logon failure!')

execute的arges参数可以接受list、tuple或dict:
如果args是一个列表或元组,%s可以用作查询中的占位符。

如果args是一个dict, %(name)s可以用作查询中的占位符。


  1. # arges参数为dict时的写法:
  2. sql = 'select name,pwd from userinfo where name=%(name)s and pwd=%(pwd)s'
  3. result = cursor.execute(sql, {'name': user, 'pwd': pwd})

commit()

在数据库里增、删、改,只是在内存中操作,所以必须要进行提交,否则插入的数据不但不会生效,还会影响到自增id.


  1. import pymysql
  2. user, pwd = input('user:'), input('pwd:')
  3. conn = pymysql.connect(
  4. host='127.0.0.1',
  5. port=3306,
  6. user='zyk',
  7. password='user@zyk',
  8. db='blog', # 要连接的数据库名称
  9. charset='utf8' # 要连接的数据库编码
  10. )
  11. # 创建游标
  12. cursor = conn.cursor()
  13. # 增
  14. sql = 'insert into userinfo(name, pwd) values (%s, %s)'
  15. effect_row = cursor.execute(sql,(user, pwd))
  16. print(effect_row) # 返回增加的记录数
  17. # 同时插入多条数据:executemany()
  18. # effect_row = cursor.executemany(sql, [("张三", '123'), ("李四", '456')])
  19. # 一定要记得提交
  20. conn.commit()
  21. # 关闭
  22. cursor.close()
  23. conn.close()


  1. import pymysql
  2. new_name = input('>>> ')
  3. conn = pymysql.connect(
  4. host='127.0.0.1',
  5. port=3306,
  6. user='zyk',
  7. password='user@zyk',
  8. db='blog', # 要连接的数据库名称
  9. charset='utf8' # 要连接的数据库编码
  10. )
  11. # 创建游标
  12. cursor = conn.cursor()
  13. # 改
  14. sql = "update userinfo set name=%s where name='zyk'"
  15. effect_row = cursor.execute(sql, new_name)
  16. print(effect_row) # 返回修改的记录数
  17. # 一定要记得提交
  18. conn.commit()
  19. # 关闭
  20. cursor.close()
  21. conn.close()


  1. import pymysql
  2. conn = pymysql.connect(
  3. host='127.0.0.1',
  4. port=3306,
  5. user='zyk',
  6. password='user@zyk',
  7. db='blog', # 要连接的数据库名称
  8. charset='utf8' # 要连接的数据库编码
  9. )
  10. cursor = conn.cursor()
  11. # 删
  12. sql = "delete from userinfo where name='张三' or name='李四'" # 同时删除多条记录
  13. effect_row = cursor.execute(sql)
  14. print(effect_row) # 返回删除的记录数
  15. # 一定要记得提交
  16. conn.commit()
  17. # 关闭
  18. cursor.close()
  19. conn.close()


查询数据库

  • fetchone()        # 获取下一行数据,第一次为首行
  • fetchall()        # 获取所有行数据
  • fetchmany(4)        # 获取4行数

表内容如下:

fetchone()


  1. import pymysql
  2. # 连接数据库
  3. conn = pymysql.connect(
  4. host='localhost',
  5. port=3306,
  6. user='zyk',
  7. password='user@zyk',
  8. db='blog',
  9. charset='utf8'
  10. )
  11. # 创建游标
  12. cursor = conn.cursor()
  13. # 执行sql语句
  14. sql = 'select * from userinfo'
  15. cursor.execute(sql)
  16. # 查询第一行数据
  17. row = cursor.fetchone()
  18. print(row)
  19. # 查询第二行数据
  20. row = cursor.fetchone()
  21. print(row)
  22. # 关闭
  23. cursor.close()
  24. conn.close()
  25. """
  26. 输出:
  27. (1, 'zyk', '___')
  28. (2, '张三', '123')
  29. """

如上:在获取行数据的时候,可以理解为开始。有一个行指针指向第一行,获取一行,他就向下移动一行。所以当行指针移动到最后一行时,便无法在获取到数据了(None)。此时我们可以使用如下方法来移动行指针:

  • cursor.scroll(1, mode='relative')        # 相对当前位置移动
  • cursor.scroll(2, mode='absolute')        # 相对绝对位置移动

值1为移动的行数,relative:可指定负数(向上移动);adsolute:0为第一行;

mode指定的是相对于当前行移动还是​相对于首行移动.​​​​​​

fetchall()


  1. import pymysql
  2. # 连接数据库
  3. conn = pymysql.connect(
  4. host='localhost',
  5. port=3306,
  6. user='zyk',
  7. password='user@zyk',
  8. db='blog',
  9. charset='utf8'
  10. )
  11. # 创建游标
  12. cursor = conn.cursor()
  13. # 执行sql语句
  14. sql = 'select * from userinfo'
  15. cursor.execute(sql)
  16. # 获取所有数据
  17. rows = cursor.fetchall()
  18. print(rows)
  19. # 关闭
  20. cursor.close()
  21. conn.close()
  22. """
  23. 输出:
  24. ((1, 'zyk', '___'), (2, '张三', '123'), (3, '李四', '456'))
  25. """

默认情况下,我们获取到的返回值是元组,可使用以下方式来返回字典:


  1. # 在实例化时,将属性cursor设置为:
  2. cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)

fetchmany()


  1. import pymysql
  2. # 连接数据库
  3. conn = pymysql.connect(
  4. host='localhost',
  5. port=3306,
  6. user='zyk',
  7. password='user@zyk',
  8. db='blog',
  9. charset='utf8'
  10. )
  11. # 创建游标
  12. cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
  13. # 执行sql语句
  14. sql = 'select * from userinfo'
  15. cursor.execute(sql)
  16. # 获取2条数据
  17. rows = cursor.fetchmany(2)
  18. print(rows)
  19. # 如果此时想要再获取已经获取过的数据,就需要移动行指针
  20. cursor.scroll(0, mode='absolute') # 移动到第一行
  21. rows = cursor.fetchall()
  22. print(rows)
  23. # 关闭
  24. cursor.close()
  25. conn.close()
  26. """
  27. 输出:
  28. [{'id': 1, 'name': 'zyk', 'pwd': '___'}, {'id': 2, 'name': '张三', 'pwd': '123'}]
  29. [{'id': 1, 'name': 'zyk', 'pwd': '___'}, {'id': 2, 'name': '张三', 'pwd': '123'}, {'id': 3, 'name': '李四', 'pwd': '456'}]
  30. """


人生中不可避免的定律

定律一:财富定律

勤劳不一定能够致富,但懒惰一定不能致富.

定律二:忙碌定律

人可以为了自己的梦想而去忙碌,但不能因为你忙碌而失去梦想.

定律三:担心定律

你越是担心的事情越有可能发生.

定律四:执着定律

任何的事情都不可过分执着,无论是风光还是难堪这些都会过去.

定律五:堵住定律

有很多越是输不起的人,越是喜欢下大赌注.

定律六:目标定律

目标太多,最后只会是失去目标,知道自己想要什么的人,能比都想要的人更容易成功.

定律七:方向定律

如果一个人不知道自己要向往哪个码头,那么不管什么风都不会是顺风.

定律八:诱惑定律

凡是抵挡不住诱惑的人,十之八九是没有经历过诱惑的人,这与诱惑大小无关.

定律九:时间定律

时间就是生命,对于男人来说是积累,对于女人来说是消耗.

年轻本无价,一身碌碌无为

让无价变为了低价,你应该珍惜自己的机会.

"

最新文章

  1. 净捡软柿子捏--jQuery
  2. 原创翻译-测试驱动开发(TDD)
  3. user32.dll
  4. Objective-C中的数据类型、常量、变量、运算符与表达式
  5. 《Java程序员面试笔试宝典》之switch使用时有哪些注意事项
  6. npm常用命令详解
  7. 微信或手机浏览器在线显示office文件(已測试ios、android)
  8. Json解析异常处理方式(JSONException: Value of type java.lang.String cannot be converted to JSONObject)
  9. CentOS下安装Nginx服务器
  10. jvm系列(十):如何优化Java GC「译」
  11. Web项目生成详解
  12. c++代码的编译
  13. Ubuntu系统安装Pyenv
  14. [WC2006]水管局长数据加强版
  15. NB学校的NB课程的NB教材——CSAPP
  16. Linux中断管理 (1)Linux中断管理机制
  17. codeforces723----C. Polycarp at the Radio
  18. 转 - spring security oauth2 password授权模式
  19. Java ThreadPoolTaskExecutor使用
  20. 创建多模块springcloud应用eureka server和client和消费端demo

热门文章

  1. Dimension reduction
  2. 208. 实现 Trie (前缀树)
  3. NlogN复杂度寻找数组中两个数字和等于给定值
  4. window环境下获取python安装的路径
  5. StringBuilder与String的区别
  6. spring面试合集
  7. LOJ138 类欧几里得算法
  8. ClassLoad
  9. java中一个类中的 this. 是什么作用
  10. 关于使用ssm与spring时,配置tomcat 虚拟目录( doBase )中的一些坑