Почему новые данные в базе данных SQLite добавляются в новую строку?

Я новичок в Python и разрабатываю бота для Telegram. Мне необходимо получить у пользователя имя, фамилию и другие данные, однако сохраняются только имя и фамилия. Остальные данные добавляются либо в новую строку, либо вообще не добавляются. Я заметил, что если в значениях id и username указать NOT NULL, это создает некоторые проблемы. Как можно сделать так, чтобы все данные добавлялись в уже существующую запись? Хочу отметить, что использование команды UPDATE не приводит к успеху, но если у вас есть другие предложенные решения с использованием UPDATE, пожалуйста, поделитесь.

Вот мой код:

<pre><code class="python">sync def add_tg(message: types.Message, state: FSMContext):
    user_id = message.from_user.id
    username = message.from_user.username
    usertg = message.text.strip()
    async with aiosqlite.connect('base.db') as db:
        await db.execute('INSERT OR IGNORE INTO user (id, username, user_tg) VALUES(?, ?, ?)', (user_id, username, usertg))
        await db.commit()

    await message.answer(text="Введите имя")
    await state.set_state(Form.name)



@start_router.message(Form.name)
async def add_name(message: types.Message):
    user_id = message.from_user.id
    username = message.from_user.username
    usertg = message.text.strip()
    name = message.text.strip()
    try:
        async with aiosqlite.connect('base.db') as db:
            await db.execute('INSERT INTO user (id, username, user_tg, name) VALUES(?, ?, ?, ?)', (user_id, username, usertg, name))
            await db.commit()
        await message.answer("Готово")
    except Exception as e:
        await message.answer(f"Произошла ошибка {e}")</code></pre> 

На данный момент я получаю ошибку: UNIQUE constraint failed: user.id. Я пробовал убирать уникальное ограничение для id и повторно добавлять, но ошибка по-прежнему остается.
  • 8 января 2025 г. 5:03
Ответы на вопрос 2
Ваше описание проблемы и предоставленный код указывают на то, что вы пытаетесь вставить новую запись в таблицу `user` с уже существующим `id`, что приводит к ошибке `UNIQUE constraint failed: user.id`. 

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

Вот несколько шагов, которые помогут исправить вашу ситуацию:

1. **Структура БД**:
   Убедитесь, что у вас есть таблица `user` с правильными полями, на которых вы хотите работать. Например:

   ```sql
   CREATE TABLE user (
       id INTEGER PRIMARY KEY,
       username TEXT,
       user_tg TEXT,
       name TEXT
   );
   ```

2. **Обновление данных**:
   Вместо попытки вставить новые данные в таблицу с существующим `id`, используйте `UPDATE`. Вот как вы можете изменить ваш код:

```python
async def add_tg(message: types.Message, state: FSMContext):
    user_id = message.from_user.id
    username = message.from_user.username
    usertg = message.text.strip()
    async with aiosqlite.connect('base.db') as db:
        await db.execute('INSERT OR IGNORE INTO user (id, username, user_tg) VALUES(?, ?, ?)', (user_id, username, usertg))
        await db.commit()

    await message.answer(text="Введите имя")
    await state.set_state(Form.name)

@start_router.message(Form.name)
async def add_name(message: types.Message):
    user_id = message.from_user.id
    name = message.text.strip()

    try:
        async with aiosqlite.connect('base.db') as db:
            await db.execute('UPDATE user SET name = ? WHERE id = ?', (name, user_id))
            await db.commit()

        await message.answer("Готово")
    except Exception as e:
        await message.answer(f"Произошла ошибка {e}")
```

В этом коде:
- Мы оставили часть, где вы добавляете пользователя в таблицу `user` с помощью `INSERT OR IGNORE`, поэтому если он уже существует, не произойдёт ошибка.
- В функции `add_name`, мы сделали `UPDATE`, чтобы обновить поле `name` для существующего пользователя.

3. **Обработка других данных**:
Если вам нужно обновить и другие поля (например, `username`, `user_tg`), вы можете также их обновить с помощью аналогичного подхода:

```python
async def add_user_details(message: types.Message):
    user_id = message.from_user.id
    username = message.from_user.username
    usertg = message.text.strip()  # Предположим, что вы получаете user_tg здесь
    name = message.text.strip()  # Имя получаете, например, в другой функции

    try:
        async with aiosqlite.connect('base.db') as db:
            await db.execute('UPDATE user SET username = ?, user_tg = ?, name = ? WHERE id = ?', (username, usertg, name, user_id))
            await db.commit()

        await message.answer("Данные обновлены.")
    except Exception as e:
        await message.answer(f"Произошла ошибка {e}")
```

Таким образом, вы сможете обновлять все необходимые данные в одной записи пользователя в таблице `user`.
Вам нужна команда INSERT INTO ... ON CONFLICT ... DO UPDATE SET ... или более актуальная UPSERT . 

В доках подробно дано описание и примеры использования.
Похожие вопросы