在Python中编写动态SQL语句

个人经验总结,有问题请指出

0x00 前期准备

import pymysql
import datetime
conn = pymysql.connect('localhost', 'root', '****', 'sakila')
cur = conn.cursor()

# 这里准备编写sql语句

cur.close()
conn.close()

0x01 占位符方式(推荐)

aid = 1
dt = datetime.datetime(2014, 9, 25, 22, 30, 27)
sql = """SELECT * FROM address WHERE address_id = %s AND last_update = %s"""

cur.execute(sql, (aid, dt))  # 多个占位符的话用tuple或list
print(cur.fetchall())
param = {'dt': datetime.datetime(2014, 9, 25, 22, 30, 27)}
sql = """SELECT * FROM address WHERE address_id = 1 AND last_update = %s"""

cur.execute(sql, parma.get('dt'))  # 一个占位符,只传相应的值或变量即可
print(cur.fetchall())

表名不可使用占位符,如需动态表名,请先使用format格式化sql语句。以下是分析,可以跳过。

# 错误示范
tb = 'address'
aid = 1
dt = datetime.datetime(2014, 9, 25, 22, 30, 27)
sql = """SELECT * FROM %s WHERE address_id = %s AND last_update = %s"""  # 表名占位符
cur.execute(sql, (tb, aid, dt))  # 此处会报错pymysql.err.ProgrammingError,提示sql语句有问题
print(cur.fetchall())

我们打断点在cur.execute(sql, (tb, aid, dt)),DEBUG进入execute方法,F8逐行执行,会有如下图在这里插入图片描述
由图可见,它在表名上加了引号,故sql语法错误。
如需动态表名,请先使用format格式化sql语句。

# 正确示范
tb = 'address'
aid = 1
dt = datetime.datetime(2014, 9, 25, 22, 30, 27)
# 因为%s已经用作占位符,我们不能再用%s来格式化表名,只能用format
sql = """SELECT * FROM {} WHERE address_id = %s AND last_update = %s""".format(tb) 
cur.execute(sql, (aid, dt))
print(cur.fetchall())

0x02 字符串格式化

  • %
tb = 'address'
aid = 1
dt = datetime.datetime(2014, 9, 25, 22, 30, 27)
# 注意last_update列加了引号
sql = """SELECT * FROM %s WHERE address_id = %d AND last_update = '%s' """ % (tb, aid, dt)
cur.execute(sql)
print(cur.fetchall())
param = {
    'tb': 'address',
    'aid': 1,
    'dt': datetime.datetime(2014, 9, 25, 22, 30, 27),
}
# 注意last_update列加了引号
sql = """SELECT * FROM %(tb)s WHERE address_id = %(aid)d AND last_update = '%(dt)s' """ % param
cur.execute(sql)
print(cur.fetchall())
  • format()
tb = 'address'
aid = 1
dt = datetime.datetime(2014, 9, 25, 22, 30, 27)
# 注意last_update列加了引号
sql = """SELECT * FROM {} WHERE address_id = {} AND last_update = '{}'""".format(tb, aid, dt)

# 参数已经是一个tuple或者list时,且位置一一对应
# param = (tb, aid, dt)
# sql = """SELECT * FROM {} WHERE address_id = {} AND last_update = '{}'""".format(*param)

# 参数已经是一个tuple或者list时,但位置不对或只需其中某些参数
# sql = """SELECT * FROM {1[0]} WHERE address_id = {0[0]} AND last_update = '{0[1]}'""".format((aid, dt)(tb,))
cur.execute(sql)
print(cur.fetchall())
param = {
    'tb': 'address',
    'aid': 1,
    'dt': datetime.datetime(2014, 9, 25, 22, 30, 27),
}
# 注意last_update列加了引号
sql = """SELECT * FROM {0[tb]} WHERE address_id = {0[aid]} AND last_update = '{0[dt]}' """.format(param)
cur.execute(sql)
print(cur.fetchall())
  • +(勿用)
tb = 'address'
aid = 1
dt = datetime.datetime(2014, 9, 25, 22, 30, 27)
sql = """SELECT * FROM """+tb+""" WHERE address_id = """+str(aid)+""" AND last_update = '"""+dt.strftime('%Y-%m-%d %H:%M:%S')+"'"
cur.execute(sql)
print(cur.fetchall())
  • 2
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值