fetchmany (1) перерывы после обновления - PullRequest
0 голосов
/ 21 января 2020

Я пишу python + функцию управления базой данных sqlite3, где каждая «продажа» в системе должна осуществляться только при наличии достаточного количества единиц товара, и каждая «поставка» может быть осуществлена ​​в любое время.

Я пытаюсь сделать запрос к базе данных и извлечь строку, затем обновить одну запись в ней и использовать ту же таблицу для выборки следующей строки. Все обновления должны быть видны для запроса следующей строки. по какой-то причине (которую я не понимаю и с удовольствием) cursor.Execute(#some update#) сломает предыдущий cursor.fetchmany(1), и это завершится выходом из режима l oop.

вот код :

def act():
    selection = """SELECT Products_tab.quantity as old_quantity, 
                    Activities_tab.quantity as new_quantity, 
                    Products_tab.id
                    FROM Products_tab inner join Activities_tab on 
                    Products_tab.id=Activities_tab.product_id"""
    cursor.execute(selection)

    while True:
        row_list = cursor.fetchmany(1)
        if row_list:
            quantity = row_list[0][0]
            change_amount = row_list[0][1]
            new_quantity = quantity + change_amount
            product_id = row_list[0][2]
            if change_amount < 0:  # sell
                if new_quantity >= 0:           # just to check if sell is possible
                    cursor.execute("""UPDATE Products_tab SET quantity=({})
                                WHERE id = ({})""".format(new_quantity, product_id))
        else:
            break

Я хотел бы понять, почему это происходит (поскольку я не мог найти какую-либо информацию в Интернете) и как ее решить. спасибо:)

1 Ответ

0 голосов
/ 21 января 2020

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

# USE TWO CURSORS
sel_cursor = conn.cursor()     
upd_cursor = conn.cursor()

selection = ...

while True: 
   sel_cursor.execute(selection)         # MOVE INSIDE LOOP
   row_list = cursor.fetchmany(1) 

   if row_list: 
       ...
       # ACTION QUERY WITH PARAMS
       upd_cursor.execute("""UPDATE Products_tab 
                             SET quantity = ? WHERE id = ?""", 
                          [new_quantity, product_id])
       conn.commit()
   else:
       break

Однако избегайте параметров l oop и Python и запустите one pure SQL с его установленным значением. основанная эффективность. Поскольку SQLite не поддерживает UPATE...JOIN или UPDATE...FROM, подзапросы используются несколько раз, включая CASE logi c для корреляции количеств продукта в обеих таблицах.

UPDATE Products_tab p
SET p.quantity = CASE
                    WHEN (SELECT quantity
                          FROM Activities_tab
                          WHERE product_id = p.id) < 0
                          AND
                         (p.quantity + (SELECT quantity
                                        FROM Activities_tab
                                        WHERE product_id = p.id)) >= 0
                    THEN (p.quantity + (SELECT quantity
                                        FROM Activities_tab
                                        WHERE product_id = p.id)) 
                    ELSE p.quantity
                 END
WHERE p.ID IN
   (SELECT product_id 
    FROM Activities_tab)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...