Как импортировать CSV в две разные таблицы SQL, которые ссылаются друг на друга Python - PullRequest
0 голосов
/ 22 апреля 2020

Цель

Я работаю над проектом CS50 Web 1, Книги (https://docs.cs50.net/ocw/web/projects/1/project1.html). Это требует, чтобы я импортировал CSV в базу данных из одной или двух таблиц. CSV выглядит так:

isbn, title, author, year
0131320931, The Hobbit, J.R.R. Tolkien, 1937

Я решил сделать две таблицы: книги и авторов. Они выглядят так:

CREATE TABLE books (book_id SERIAL PRIMARY KEY, isbn VARCHAR(13), title VARCHAR(26021), author references authors(author_id),  year INT);
CREATE TABLE authors (author_id SERIAL PRIMARY KEY, name VARCHAR(255));

Моя цель - использовать скрипт Python с SQLAlchemy для импорта CSV в обе эти таблицы.

Выпуск

Моя проблема заключается в импорте CSV таким образом, что внешний идентификатор в книгах ссылается на авторов. Мой текущий код таков:

def main():
    f = open("books.csv")
    reader = csv.reader(f)
    for isbn, title, author, year in reader:
        db.execute("INSERT INTO authors (name) VALUES(:author)",
                   {"author": author})
        db.execute("INSERT INTO books (isbn, title, year) VALUES(:isbn, :title, :year)", {
                   "isbn": isbn,
                   "title": title
                   "year": year})
    db.commit()

Результат:

 book_id |    isbn    |         title         | author | year 
---------+------------+-----------------------+--------+------
       1 | 0380795272 | Krondor: The Betrayal |   *    | 1998
       2 | 1416949658 | The Dark Is Rising    |        | 1973
*Should be "1", the foreign key for Raymond E. Feist.
 author_id |       name       
-----------+------------------
         1 | Raymond E. Feist
         2 | Susan Cooper

Я не могу обернуться, чтобы импортировать их одновременно, генерирует внешний ключ в авторе. Я думал о создании временной таблицы и использовании запросов SELECT WHERE, но это выглядело как уловка. Я также пытался использовать вложенную функцию во втором INSERT в книгах, используя авторов, но это, похоже, не сработало.

Я использую PostgreSQL.

Также приветствуется любая помощь в качестве отзыва о том, как я поставил вопрос!

Спасибо!

1 Ответ

0 голосов
/ 23 апреля 2020

Решение

Я смог понять это. Я использовал предложение PostgreSQL ON CONFLICT DO NOTHING после создания уникального столбца authors.name. Единственное предостережение, которое в этой структуре данных я считаю неизбежным, - это авторы с одинаковыми именами. Я также не уверен, как бы я включил книги, написанные несколькими авторами.

Код

def main():
    f = open("books.csv")
    reader = csv.reader(f)
    reader.__next__
    for isbn, title, author, year in reader:
        db.execute("INSERT INTO authors (name) VALUES(:author) ON CONFLICT (name) DO NOTHING",
                   {"author": author})
        db.execute("INSERT INTO books (isbn, title, author, year) VALUES(:isbn, :title, (SELECT author_id FROM authors WHERE name = :author), :year)", {
                   "isbn": isbn,
                   "author": author,
                   "title": title,
                   "year": year})
    db.commit()

Вывод

 author_id |       name       
-----------+------------------
        38 | Raymond E. Feist
 book_id |    isbn    |         title         | author | year 
---------+------------+-----------------------+--------+------
      38 | 0380795272 | Krondor: The Betrayal |     38 | 1998

Примечание : Случайно, что они используют один и тот же идентификатор, потому что они были первыми введенными записями.

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