如何使用 'pymysql' 打印发送到 mySQL 的查询?
How to print the query being sent to mySQL using 'pymysql'?
假设我有以下代码:
with open('saved_response.json') as data_file:
#data_ordered = json.load(data_file, object_pairs_hook=OrderedDict)
response=json.load(data_file)
for user_data in response['itemList']:
field_names=""
field_values=[]
for i in user_data:
field_names+=","+i
field_values.append(user_data[i])
print(field_names[1:])
print(field_values)
with con.cursor() as c:
c.execute("INSERT into user(%s) values(%s);",(field_names[1:],field_values))
我收到以下错误:
ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''id,parentId,username,creationTime,role,state,userProfile') values((562949953421' at line 1")
有什么方法可以打印发送到 MySQL 执行的 SQL 查询,以便我们可以解决这样的语法错误?
此外,将不胜感激此错误的解决方案。
with open('saved_response.json') as data_file:
#data_ordered = json.load(data_file, object_pairs_hook=OrderedDict)
response=json.load(data_file)
for user_data in response['itemList']:
field_names=[]
field_values=[]
for i in user_data:
field_names.append(i)
field_values.append(user_data[i])
print(field_names)
print(field_values)
with con.cursor() as c:
c.execute("INSERT into user(%s) values(%s);",(','.join(field_names), ','.join(str(field) for field in field_values)))
问题是您将列表传递到 %s
。您必须用逗号分隔 field_values。
正如评论中所指出的,PyMySQL 游标对象也具有未记录的属性 _last_executed
,其中包含已发送的查询。
您的语法错误是由于尝试使用占位符传递标识符(在本例中为列名)造成的。从报错信息可以看出
'id,...,userProfile') values((...
已发送。换句话说,这些列作为单个(字符串)文字发送。不幸的是,不可能使用占位符来传递标识符。这种情况需要构建查询字符串。您应该将这些列列入白名单,然后构建您的查询。
由于双括号,VALUES 子句也有问题。事实证明,PyMySQL 知道如何对作为 "scalar" 个参数传递的序列进行编码:
In [65]: with conn.cursor() as cur:
...: cur.execute('select %s in %s',
...: ('z', ['\');DROP TABLE students -- ', 'x', 'y']))
...: print(cur.fetchone())
...: print(cur._last_executed)
...:
(0,)
select 'z' in ('\');DROP TABLE students -- ','x','y')
因此,不要将值列表占位符括在方括号中,只需在值列表应放置的位置放置一个占位符即可。
ALLOWED_COLUMNS = {'id', 'parentId', 'username', 'creationTime',
'role', 'state', 'userProfile'}
for user_data in response['itemList']:
field_names, field_values = zip(*user_data.items())
unknown = set(field_names) - ALLOWED_COLUMNS
if unknown:
raise RuntimeError(f"Unknown columns: {unknown}")
field_names = ','.join(field_names)
with con.cursor() as c:
# Note: field names have been whitelisted. Normally one should avoid
# string formatting SQL queries.
c.execute(f"INSERT INTO user ({field_names}) VALUES %s", (field_values,))
最后一点,如果您的专栏确实使用混合大小写并且是这样创建的,您可能需要引用它们。
try:
c.execute("INSERT into user(%s) values(%s);",(field_names[1:],field_values))
except:
print(c._last_executed)
raise
假设我有以下代码:
with open('saved_response.json') as data_file:
#data_ordered = json.load(data_file, object_pairs_hook=OrderedDict)
response=json.load(data_file)
for user_data in response['itemList']:
field_names=""
field_values=[]
for i in user_data:
field_names+=","+i
field_values.append(user_data[i])
print(field_names[1:])
print(field_values)
with con.cursor() as c:
c.execute("INSERT into user(%s) values(%s);",(field_names[1:],field_values))
我收到以下错误:
ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''id,parentId,username,creationTime,role,state,userProfile') values((562949953421' at line 1")
有什么方法可以打印发送到 MySQL 执行的 SQL 查询,以便我们可以解决这样的语法错误? 此外,将不胜感激此错误的解决方案。
with open('saved_response.json') as data_file:
#data_ordered = json.load(data_file, object_pairs_hook=OrderedDict)
response=json.load(data_file)
for user_data in response['itemList']:
field_names=[]
field_values=[]
for i in user_data:
field_names.append(i)
field_values.append(user_data[i])
print(field_names)
print(field_values)
with con.cursor() as c:
c.execute("INSERT into user(%s) values(%s);",(','.join(field_names), ','.join(str(field) for field in field_values)))
问题是您将列表传递到 %s
。您必须用逗号分隔 field_values。
正如评论中所指出的,PyMySQL 游标对象也具有未记录的属性 _last_executed
,其中包含已发送的查询。
您的语法错误是由于尝试使用占位符传递标识符(在本例中为列名)造成的。从报错信息可以看出
'id,...,userProfile') values((...
已发送。换句话说,这些列作为单个(字符串)文字发送。不幸的是,不可能使用占位符来传递标识符。这种情况需要构建查询字符串。您应该将这些列列入白名单,然后构建您的查询。
由于双括号,VALUES 子句也有问题。事实证明,PyMySQL 知道如何对作为 "scalar" 个参数传递的序列进行编码:
In [65]: with conn.cursor() as cur:
...: cur.execute('select %s in %s',
...: ('z', ['\');DROP TABLE students -- ', 'x', 'y']))
...: print(cur.fetchone())
...: print(cur._last_executed)
...:
(0,)
select 'z' in ('\');DROP TABLE students -- ','x','y')
因此,不要将值列表占位符括在方括号中,只需在值列表应放置的位置放置一个占位符即可。
ALLOWED_COLUMNS = {'id', 'parentId', 'username', 'creationTime',
'role', 'state', 'userProfile'}
for user_data in response['itemList']:
field_names, field_values = zip(*user_data.items())
unknown = set(field_names) - ALLOWED_COLUMNS
if unknown:
raise RuntimeError(f"Unknown columns: {unknown}")
field_names = ','.join(field_names)
with con.cursor() as c:
# Note: field names have been whitelisted. Normally one should avoid
# string formatting SQL queries.
c.execute(f"INSERT INTO user ({field_names}) VALUES %s", (field_values,))
最后一点,如果您的专栏确实使用混合大小写并且是这样创建的,您可能需要引用它们。
try:
c.execute("INSERT into user(%s) values(%s);",(field_names[1:],field_values))
except:
print(c._last_executed)
raise