mysql数据库感悟_python对于mysql数据库操作类的相关方法及感悟

概述

本着磨刀不误砍柴工、高内聚低耦合的代码原则,带着心中向往的行云流水的敲代码向往,秉承绝不走回头路、我的代码我最屌的原则记录了此文。

对于数据库数据的操作,力要写一个万能、通用且高效率的数据库操作类。

话不多说,直接上代码:

import pymysql

class MysqlHelper:

def __init__(self):

self._user = db_user

self._password = db_pwd

self._charset = 'utf8'

self._port = port

self._host = db_host

self._db_name = db_name

self._conn = self.connect_mysql()

if self._conn:

self._cursor = self._conn.cursor()

def connect_mysql(self):

"""

连接数据库

:return:

"""

conn = pymysql.connect(host=self._host,

user=self._user,

passwd=self._password,

db=self._db_name,

port=self._port,

cursorclass=pymysql.cursors.DictCursor,

charset=self._charset,

)

return conn

def close(self):

"""

关闭数据库连接

:return:

"""

self._cursor.close()

self._conn.close()

def execute(self, *args, params=None):

"""

执行多条sql

:param params:

:param args:

:return:

"""

if params is None:

params = []

effect = 0

for sql in args:

num = self._cursor.execute(sql, params)

effect += num

self._conn.commit()

self.close()

return effect

def select_multi(self, *args, params=None):

"""

查询语句,可以执行多条查询

:param args:

:param params:

:return: 返回元祖res:结果,num查询出行数

"""

if params is None:

params = []

i = 1

res = {}

for sql in args:

num = self._cursor.execute(sql, params)

sql_results = self._cursor.fetchall()

res['result%s' % i] = sql_results

res['effect%s' % i] = num

i += 1

self.close()

return res

def select(self, sql, act='all', params=None):

"""

查询语句方法

:param act:

:param sql:

:param params:

:return: 返回字典res:结果,num查询出行数

"""

global res

if params:

pass

else:

params = []

if act == 'all':

num = self._cursor.execute(sql)

sql_results = self._cursor.fetchall()

res = {

'result': sql_results,

'effect': num

}

self.close()

return res

好了,以上代码就是一个基本上可以直接使用的数据库操作类了,简述来说呢就是select_multi方法用来执行多条查询sql语句,select方法来执行单条语句(区别不大,但是各有用处),execute方法来执行多条操作语句。

之所以写了一个select_multi方法和execute通用多条语句就是用来仿写数据库中的事务操作,减少了每条语句对于数据库的连接、访问、关闭的这一系列操作,提高了效率。

但是对于cursor().execute()方法又是比较特殊的。

一、问题所在

先粘一段源代码:

def execute(self, query, args=None):

"""Execute a query

:param str query: Query to execute.

:param args: parameters used with query. (optional)

:type args: tuple, list or dict

:return: Number of affected rows

:rtype: int

If args is a list or tuple, %s can be used as a placeholder in the query.

If args is a dict, %(name)s can be used as a placeholder in the query.

"""

while self.nextset():

pass

query = self.mogrify(query, args)

result = self._query(query)

self._executed = query

return result

可以看出来execute方法里面有两个参数而对于args是非必传,查看过文档,在调用时的param参数在使用时是用来避免sql注入而存在的,这样就能避免了恶意攻击数据库等行为。但是了解过这点之后,在某些sql语句中例如

DATE_FORMAT(CURRENT_DATE,'%Y-%m-%d')

日期函数中的%Y却又会报错,网上很多方法都是将单%变成双%避免被认定为占位符而存在。

4504683135b4

报错截图.jpg

二、水落石出

对于Python中的三引号,将单%变为双%在更新之后又不好用了,会直接认定为是字符串%%,好坑......

于是再次观察源代码在execute()中的mogrify()方法

def mogrify(self, query, args=None):

"""

Returns the exact string that is sent to the database by calling the

execute() method.

This method follows the extension to the DB API 2.0 followed by Psycopg.

"""

conn = self._get_db()

if PY2: # Use bytes on Python 2 always

query = self._ensure_bytes(query, encoding=conn.encoding)

if args is not None:

query = query % self._escape_args(args, conn)

return query

传入了上层函数传来的args参数、而在函数中对于args进行了一次判定,而对于避免sql注入而传入的param参数,尽管为空,但是是一个空列表而非None对象,所以会卡在self._escape_args(args, conn)方法上,结果清晰明了了。

那么,改进!

def select(self, sql, act='all'):

"""

查询语句方法

:param act:

:param sql:

:param params:

:return: 返回字典res:结果,num查询出行数

"""

global res

if act == 'all':

num = self._cursor.execute(sql)

sql_results = self._cursor.fetchall()

res = {

'result': sql_results,

'effect': num

}

self.close()

return res

这样就通用的多了,舒服。当然,也可以自己加很多种操作方法,那就取决于你啦。玩的开心。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值