В чем причина некорректного выполнения запроса в MySQL?

Я только начинаю изучать MySQL, в частности aiomysql, и понял, что они практически идентичны, за исключением асинхронности. Однако, когда я запустил следующий код: 

(main.py)
```python
import db 
loop = db.loop 
loop.run_until_complete(db.create()) 
loop.run_until_complete(db.set('о',  'i')) 
```

(db.py)
```python
import asyncio 
import aiomysql 
from config_reader import config 

loop = asyncio.get_event_loop() 

async def create(): 
    conn = await aiomysql.connect(host=config.mysql_host.get_secret_value(), 
                                   user=config.mysql_user.get_secret_value(), 
                                   password=config.mysql_password.get_secret_value(), 
                                   db=config.mysql_db_name.get_secret_value(), 
                                   loop=loop) 

    async with conn.cursor() as cur: 
        await cur.execute("""CREATE TABLE IF NOT EXISTS users ( 
            id INT AUTO_INCREMENT, 
            description TEXT, 
            icon TEXT, 
            PRIMARY KEY (id))""") 
        await conn.commit() 

    conn.close() 

async def get(column, what, is_what): 
    conn = await aiomysql.connect(host=config.mysql_host.get_secret_value(), 
                                   user=config.mysql_user.get_secret_value(), 
                                   password=config.mysql_password.get_secret_value(), 
                                   db=config.mysql_db_name.get_secret_value(), 
                                   loop=loop) 

    async with conn.cursor() as cur: 
        await cur.execute(f"SELECT {column} FROM users WHERE {what} = {is_what}") 
        await conn.commit() 

    conn.close() 

async def set(d, i): 
    conn = await aiomysql.connect(host=config.mysql_host.get_secret_value(), 
                                   user=config.mysql_user.get_secret_value(), 
                                   password=config.mysql_password.get_secret_value(), 
                                   db=config.mysql_db_name.get_secret_value(), 
                                   loop=loop) 
```

я сталкиваюсь с проблемами. Можете подсказать, что может быть не так в моем коде?
  • 12 декабря 2024 г. 18:03
Ответы на вопрос 1
Ваш код имеет несколько проблем, которые могут приводить к некорректному выполнению запросов в MySQL. Давайте разберем ключевые моменты и предложим улучшения.

1. **Отсутствие операций в функции `set()`:** Ваша функция `set()` не содержит логики для выполнения SQL-запросов. Вам нужно определить, что именно вы хотите сделать с переменными `d` и `i`. Например, если вы хотите вставить данные в таблицу `users`, вам нужно использовать SQL-запрос для вставки данных.

   Пример реализации для добавления записи:
   ```python
   async def set(d, i):
       conn = await aiomysql.connect(host=config.mysql_host.get_secret_value(), 
                                      user=config.mysql_user.get_secret_value(), 
                                      password=config.mysql_password.get_secret_value(), 
                                      db=config.mysql_db_name.get_secret_value(), 
                                      loop=loop) 
       async with conn.cursor() as cur: 
           await cur.execute("INSERT INTO users (description, icon) VALUES (%s, %s)", (d, i)) 
           await conn.commit() 
       conn.close()
   ```

2. **Правильное использование параметров в запросе:** В функции `get()` вы не используете безопасный способ передачи параметров в SQL-запрос. Это может привести к SQL-инъекции. Вместо форматирования строки используйте плейсхолдеры, как показывается в примере выше.

3. **Закрытие соединения:** Вы закрываете соединение с базой данных в конце каждой функции, что правильно. Однако, если во время выполнения запроса произойдет исключение, соединение может не закрыться. Вместо закрытия соединения вручную, вы можете использовать `async with` для автоматического управления контекстом соединения:

   ```python
   async def some_function():
       async with aiomysql.connect(...) as conn:
           async with conn.cursor() as cur:
               # ваш код
   ```

4. **Использование правильного типа данных:** Если вы работаете с типами данных в SQL, убедитесь, что данные, которые вы передаете, соответствуют ожидаемым типам. Например, если поле `description` ожидает текст, передавайте строку.

Вот обновленный код для вашей `db.py`, чтобы сделать его более безопасным и функциональным:

```python
import asyncio
import aiomysql
from config_reader import config

loop = asyncio.get_event_loop()

async def create():
    async with aiomysql.connect(host=config.mysql_host.get_secret_value(), 
                                 user=config.mysql_user.get_secret_value(), 
                                 password=config.mysql_password.get_secret_value(), 
                                 db=config.mysql_db_name.get_secret_value(), 
                                 loop=loop) as conn:
        async with conn.cursor() as cur:
            await cur.execute("""CREATE TABLE IF NOT EXISTS users ( 
                id INT AUTO_INCREMENT PRIMARY KEY, 
                description TEXT, 
                icon TEXT)""")
            await conn.commit()

async def get(column, what, is_what):
    async with aiomysql.connect(host=config.mysql_host.get_secret_value(), 
                                 user=config.mysql_user.get_secret_value(), 
                                 password=config.mysql_password.get_secret_value(), 
                                 db=config.mysql_db_name.get_secret_value(), 
                                 loop=loop) as conn:
        async with conn.cursor() as cur:
            await cur.execute(f"SELECT {column} FROM users WHERE {what} = %s", (is_what,))
            result = await cur.fetchall()
            return result

async def set(d, i):
    async with aiomysql.connect(host=config.mysql_host.get_secret_value(), 
                                 user=config.mysql_user.get_secret_value(), 
                                 password=config.mysql_password.get_secret_value(), 
                                 db=config.mysql_db_name.get_secret_value(), 
                                 loop=loop) as conn:
        async with conn.cursor() as cur:
            await cur.execute("INSERT INTO users (description, icon) VALUES (%s, %s)", (d, i))
            await conn.commit()
```

Проверьте эти изменения и попробуйте снова запустить ваш код. Помните о надлежащей обработке ошибок, если вы столкнетесь с другими проблемами.
Похожие вопросы