连接到数据库
import pymysql
# 创建链接得到一个链接对象
conn = pymysql.Connect(
host="127.0.0.1", # 数据库服务器主机地址
user="root", # 用户名
password="root", # 密码
database="test", #数据库名称
port=3306, # 端口号 可选 整型
charset="utf8" # 编码 可选
)
和命令行一直的是是要指定IP端口,用户授权,不过用户要操作的数据库必须要在pymysql连接之前就要存在,不然就要报错。
获得游标
,类比命令行,登录命令行之后会有mysql>
的提示符提示你进行操作,用代码操作数据库需要获得相应的游标,传入的pymysql.cursors.DictCursor
参数是指定返回的结果是字典类型的数据,pymysql
会给字典加上字典容器,最后返回的是列表,列表的元素时字典,字典的键值是对应的字段和数据
cursor = conn.cursor(pymysql.cursors.DictCursor) # 将查询结果做成字典的格式
执行SQL语句
我们通常将sql语句放在字符串中,比如
select_sql = ""select * from table_name"" # 要在sql语句中指定数据表了,要不然查不到数据
insert_sql = "insert into table_name( name,age) values(%s,%s)"%("ruhai",18)
updata_sql = "update user set username='superamdin' where name = admin"
我们将写好的SQL语句交给cursor.execute()
来执行,就相当于你把命令敲在命令行中并敲了一下回车,得到sql语句的执行结果。
cursor.execute(select_sql)
cursor.commit() # 因为pymysql 模块默认是启用事务的 你的sql语句 如果不提交 相当于没有执行
获得结果
我们用一个变量值来获得查询的结果
res = cursor.execute(select_sql)
直接打印可以得到结果的条目数
print(res)
获得具体数据
cursor.fetchone()
cursor.fetchall()
游标的移动
在数据库中,游标是一个十分重要的概念。游标提供了一种对从表中检索出的数据进行操作的灵活手段,就本质而言,游标实际上是一种能从包括多条数据记录的结果集中每次提取一条记录的机制。游标总是与一条SQL 查询语句相关联因为游标由结果集(可以是零条、一条或由相关的选择语句检索出的多条记录)和结果集中指向特定记录的游标位置组成。当决定对结果集进行处理时,必须声明一个指向该结果集的游标。如果曾经用C 语言写过对文件进行处理的程序,那么游标就像您打开文件所得到的文件句柄一样,只要文件打开成功,该文件句柄就可代表该文件。对于游标而言,其道理是相同的。
cursor.scroll(1,mode='relative') # 相对当前位置移动【1:表示向下移动一行,-1:表示向上移动一行】
cursor.scroll(1,mode='absolute') # 相对绝对位置移动 【1:表示向上移动一行,-1:表示向下移动一行】
敏感信息的防护
防止sql注入
来看下面的代码
username=input()
password =input()
# 正常构造语句的情况
sql = "select user,pwd from User where user='%s' and pwd='%s'" % (username,password)
row_count = cursor.execute(sql)
其实用户可以这样输入实现免帐号登录:
username: ‘or 1 = 1 –-
password:
如若没有做特殊处理,那么这个非法用户直接登陆进去了.
当输入了上面的用户名和密码,服务端的sql就变成:
sql = "select user,pwd from User where user=‘'or 1 = 1 –-' and pwd='%s'"
因为条件后面username=”or 1=1
用户名等于 空 或1=1 那么这个条件一定会成功;然后后面加两个-,这意味着注释,它将后面的语句注释,让他们不起作用,这样语句永远都能正确执行,用户轻易骗过系统,获取合法身份。
使用pymysql提供的参数化语句防止注入
#执行参数化查询
row_count=cursor.execute("select user,pwd from User where user='%s' and pwd='%s'" ,(username,password))
#execute()函数本身就有接受SQL语句变量的参数位,只要正确的使用(直白一点就是:使用”逗号”,而不是”百分号”)就可以对传入的值进行correctly转义,从而避免SQL注入的发生。
数据一致性验证
小明有100块 准备给小花转50,如果这个时候突然发生了一些事情导致这个数据值存成功了一半,把小明的钱从系统中扣件掉了,但是没有给小花加上去,那么就会造成数据的不一致,这个时候应该加上容错机制提高程序的健壮性,和数据的安全。
try:
cursor.execute("update moneyTable set money = money - 50 where name = '小明'")
#如果小花的账户出问题了 无法更新数据 那就需要回滚
cursor.execute("update moneyTable set money = money + 50 where name = '小花'")
conn.commit()
except:
conn.rollback()
关闭连接
cursor.close()
conn.close()
操作数据库的完整代码
import pymysql
conn = pymysql.Connect(
host="127.0.0.1",
user="root",
password="admin",
database="day42",
port=3306,
charset="utf8"
)
cursor = conn.cursor(pymysql.cursors.DictCursor)
sql = "insert into user(username,pwd) values(%s,%s)"
try:
cursor.execute(sql,args= (user,name))
conn.commit()
except:
conn.rollback()
cursor.close()
conn.close()