Как напечатать запрос, отправляемый в mySQL, используя 'pymysql'?

0

Скажем, у меня есть следующий код:

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")

Есть ли способ распечатать SQL-запрос, отправляемый в MySQL для выполнения, чтобы мы могли разрешить синтаксические ошибки, подобные этому? Также будет оценено решение этой ошибки.

Теги:
python-3.x
mysql-python
pymysql

2 ответа

0
Лучший ответ

Как отмечено в комментариях, также объекты курсора PyMySQL имеют недокументированный атрибут _last_executed, который содержит отправленный запрос.

Ваши синтаксические ошибки являются результатом попытки передать идентификаторы, в этом случае имена столбцов, используя placeholder (s). Из сообщения об ошибке вы можете видеть, что

'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,))

В заключение, если ваши столбцы действительно используют смешанный случай и были созданы как таковые, вам, возможно, придется процитировать их.

-2
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. Вы должны разделить поле_значения запятыми.

  • 0
    Не работает для значений 'int' в field_values.
  • 0
    Я изменил код, теперь он должен работать.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню