@xpril

При обновлении данных в БД sqlite3, обновляет только 1 строку, как сделать, что бы обновляло сразу все?

Цикл for в БД перебирает все vk_id, и при передаче их UPDATE, обновляется лишь один, самый первый в бд.

import sqlite3
import vk_api
import datetime
from vk_api.bot_longpoll import VkBotLongPoll, VkBotEventType

token = "token vk"
vk = vk_api.VkApi(token=token)
longpoll = VkBotLongPoll(vk, group_vk_id)

db = sqlite3.connect("vitaliy.db")
qwe = db.cursor()

qwe.execute(""" CREATE TABLE IF NOT EXISTS stata (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    vk_id INTEGER NOT NULL UNIQUE,
    nickname TEXT DEFAULT "Unnamed",
    coins BIGINT DEFAULT 5000,
    prem TEXT DEFAULT "Нет",
    dohod BIGINT DEFAULT 1000
) """)

##################################################################################################

def sender(chat_id, message):
    vk.method("messages.send", {"chat_id": chat_id, "message": message, "disable_mentions": 1, "random_id": 0})


##################################################################################################

while True:
    now = datetime.datetime.now()
    timeC = now.second
    if timeC != datetime.datetime.now().second:
        for i in qwe.execute(""" SELECT vk_id FROM stata """):
            qwe.executemany(""" 
                UPDATE stata
                SET coins = coins + dohod
                WHERE vk_id = ?
            """, (i,))
            db.commit()
    else:
        None
    timeC = datetime.datetime.now().second
  • Вопрос задан
  • 163 просмотра
Пригласить эксперта
Ответы на вопрос 3
shurshur
@shurshur
Сисадмин, просто сисадмин...
cursor.execute возвращает генератор, который возвращает кортежи значений. Таким образом, в конструкции:

for i in qwe.execute(""" SELECT vk_id FROM stata """):


значением i будет не значение vk_id, а кортеж из одного значения (vk_id,).

Далее, в этом цикле делается запрос с (i,), который даёт ((vk_id,),), то есть одно значение. Кроме того, внутри итерации по курсору выполняется другой запрос с тем же курсором с затиранием внутренних данных курсора от предыдущего запроса, поэтому при заходе на вторую итерацию уже не возвращается ничего. Получается один запрос по одному vk_id. Всё работает ровно так, как написано.

Что тут можно сделать?

Вариант 1. В executemany имеет смысл передать список не из одного значения, а из множества (иначе нет смысла в executemany, проще обычный execute). Например, их можно получить путём накопления в цикле в список с последующим отдельным (вне цикла) вызовом executemany. Но если с данными запроса ничего особого делать не нужно, то и цикл тут лишний, можно получить всё сразу через fetchall().

Вариант 2. Обойтись средствами SQL. Примеры:

-- добавить всем 1
UPDATE stata SET coins = coins+1;
-- добавить удвоенный доход всем с вип-статусом, если срок его действия ещё не истёк
UPDATE stata SET coins = coins+dohod*2 WHERE vip_status=1 AND vip_status_end>=NOW();
Ответ написан
Комментировать
@rPman
потому что там не может быть больше 1 записи из-за этого:

vk_id INTEGER NOT NULL UNIQUE,
Ответ написан
@galaxy
UPDATE stata
   SET coins = coins + dohod

все.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы