Python sqlite3: L oop через строки из table_a останавливается при вставке в table_b - PullRequest
1 голос
/ 12 июля 2020

Попытка пройти l oop через строки из table_a, передать их в функцию и вставить выходные данные в table_b. Я могу пройти l oop через строки из table_a, но как только я пытаюсь вставить что-то в table_b, мой скрипт просто останавливается.

with sqlite3.connect(db_path) as db:
    cursor = db.cursor()

cursor.execute("""SELECT * FROM cars""")

for row in cursor:
  car_price = get_car_price(row[0])
  cursor.execute("""INSERT INTO car_prices (price, car_id) VALUES (?,?);""",(car_price, row[0]))

output:

[Finished in 1.0s]

Это странно, потому что приведенное ниже работает, но как только я пытаюсь выполнить таблицу car_prices (как в предыдущем коде), код просто заканчивается на первой итерации.

with sqlite3.connect(db_path) as db:
    cursor = db.cursor()

cursor.execute("""SELECT * FROM cars""")

for row in cursor:
  print(row)

вывод:

(1, "car_1")
(2, "car_2")
...
(n, "car_n")
[Finished in 0.7s]

Как и просили, вот схема .schema:

sqlite> .schema
CREATE TABLE IF NOT EXISTS "cars" (
        "id"    integer NOT NULL,
        "name"  text NOT NULL,
        "website_url"   text NOT NULL,
        PRIMARY KEY("id")
);
CREATE TABLE IF NOT EXISTS "car_prices" (
        "price_id"      integer,
        "price" NUMERIC NOT NULL,
        "car_id"        integer NOT NULL,
        PRIMARY KEY("price_id"),
        FOREIGN KEY("car_id") REFERENCES "cars"("id")

1 Ответ

1 голос
/ 15 июля 2020

Проблема в том, что вы повторно используете курсор, отбрасывая результаты своего первого запроса.

Вот минимальный запускаемый пример (вы могли получить более быстрый ответ, если бы включил это в ваш вопрос, так как людям потребовалось бы меньше усилий для участия):

#!/usr/bin/env python3

import sqlite3
import sys

def get_car_price(carid):
    return carid * 11 + 101

with sqlite3.connect(':memory:') as db:
    db.execute('''
        CREATE TABLE IF NOT EXISTS "cars" (
            "id"    integer NOT NULL,
            "name"  text NOT NULL,
            "website_url"   text NOT NULL,
            PRIMARY KEY("id")
        )
    ''')
    db.execute('''
        CREATE TABLE IF NOT EXISTS "car_prices" (
            "price_id"      integer,
            "price" NUMERIC NOT NULL,
            "car_id"        integer NOT NULL,
            PRIMARY KEY("price_id"),
            FOREIGN KEY("car_id") REFERENCES "cars"("id")
        )
    ''')
    for ix, name in enumerate(('Lolvo', 'Yotoya', 'Edison')):
        url = 'http://example.com/' + name.lower()
        db.execute('INSERT INTO cars VALUES(?,?,?)', (ix, name, url))

    cursor = db.cursor()
    if 'sep' in sys.argv:
        insertcursor = db.cursor()
    else:
        insertcursor = cursor


cursor.execute("""SELECT * FROM cars""")
for row in cursor:
    car_price = get_car_price(row[0])
    print(row, car_price)
    insertcursor.execute("""INSERT INTO car_prices (price, car_id) VALUES (?,?);""",(car_price, row[0]))

cursor.execute('''SELECT * FROM car_prices''')
for row in cursor:
    print('car_prices:', row)

При запуске без аргументов он будет использовать тот же курсор, воспроизводя вашу проблему:

python-sqlite-stops$ ./stuff.py
(0, 'Lolvo', 'http://example.com/lolvo') 101
car_prices: (1, 101, 0)

Укажите «sep» в качестве аргумента, и он будет использовать отдельный курсор для вставки, исправляя вашу проблему:

python-sqlite-stops$ ./stuff.py sep
(0, 'Lolvo', 'http://example.com/lolvo') 101
(1, 'Yotoya', 'http://example.com/yotoya') 112
(2, 'Edison', 'http://example.com/edison') 123
car_prices: (1, 101, 0)
car_prices: (2, 112, 1)
car_prices: (3, 123, 2)

Вы можете сделать это еще проще, просто используя db.execute() для вставок; нет cursor() звонок необходим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...