Как отмечено в комментариях, также объекты курсора PyMySQL имеют недокументированный атрибут _last_executed
, который содержит отправленный запрос.
Ваши синтаксические ошибки являются результатом попытки передать идентификаторы, в данном случае имена столбцов, с использованием заполнителей. Из сообщения об ошибке видно, что
'id,...,userProfile') values((...
было отправлено. Другими словами, столбцы были отправлены как один (строковый) литерал. К сожалению, невозможно использовать заполнители для передачи идентификаторов. Этот случай требует построения строки запроса. Вы должны внести в белый список столбцы и затем построить свой запрос.
Предложение VALUES также проблематично из-за двойных скобок. Оказывается, PyMySQL знает, как кодировать последовательности, передаваемые как «скалярные» аргументы:
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,))
В заключение: если ваши столбцы действительно используют смешанный регистр и были созданы как таковые, вам, возможно, придется их заключить в кавычки.