Загрузка данных
import sqlite3
from datetime import date, timedelta
def create_tables(conn):
cursor = conn.cursor()
cursor.execute("PRAGMA foreign_keys = ON;")
cursor.execute('''
CREATE TABLE IF NOT EXISTS authors (
id INTEGER PRIMARY KEY AUTOINCREMENT,
last_name TEXT NOT NULL,
first_name TEXT NOT NULL,
patronymic TEXT,
year_of_birth INTEGER
)
''')
cursor.execute('''
CREATE TABLE IF NOT EXISTS subjects (
id INTEGER PRIMARY KEY AUTOINCREMENT,
subject TEXT NOT NULL UNIQUE
)
''')
cursor.execute('''
CREATE TABLE IF NOT EXISTS books (
id INTEGER PRIMARY KEY AUTOINCREMENT,
subject_id INTEGER,
book_name TEXT NOT NULL,
annotation TEXT,
year_of_publication INTEGER,
publisher TEXT,
number_of_racks INTEGER,
number_of_books INTEGER,
books_in_use INTEGER,
FOREIGN KEY (subject_id) REFERENCES subjects(id) ON DELETE SET NULL
)
''')
cursor.execute('''
CREATE TABLE IF NOT EXISTS customers (
id INTEGER PRIMARY KEY AUTOINCREMENT,
last_name TEXT NOT NULL,
first_name TEXT NOT NULL,
patronymic TEXT,
date_of_birth TEXT,
phone_number TEXT,
home_address TEXT
)
''')
cursor.execute('''
CREATE TABLE IF NOT EXISTS book_author (
id INTEGER PRIMARY KEY AUTOINCREMENT,
book_id INTEGER,
author_id INTEGER,
FOREIGN KEY (book_id) REFERENCES books(id) ON DELETE CASCADE,
FOREIGN KEY (author_id) REFERENCES authors(id) ON DELETE CASCADE,
UNIQUE(book_id, author_id)
)
''')
cursor.execute('''
CREATE TABLE IF NOT EXISTS author_subject (
author_id INTEGER,
subject_id INTEGER,
PRIMARY KEY (author_id, subject_id),
FOREIGN KEY (author_id) REFERENCES authors(id) ON DELETE CASCADE,
FOREIGN KEY (subject_id) REFERENCES subjects(id) ON DELETE CASCADE
)
''')
cursor.execute('''
CREATE TABLE IF NOT EXISTS borrows (
id INTEGER PRIMARY KEY AUTOINCREMENT,
book_id INTEGER,
customer_id INTEGER,
date_of_issue TEXT NOT NULL,
return_date TEXT, -- NULL означает, что книга ещё не возвращена
FOREIGN KEY (book_id) REFERENCES books(id) ON DELETE RESTRICT,
FOREIGN KEY (customer_id) REFERENCES customers(id) ON DELETE RESTRICT
)
''')
conn.commit()
print("✅ Таблицы созданы (или уже существовали).")
def insert_test_data(conn):
cursor = conn.cursor()
cursor.execute("DELETE FROM borrows")
cursor.execute("DELETE FROM book_author")
cursor.execute("DELETE FROM author_subject")
cursor.execute("DELETE FROM books")
cursor.execute("DELETE FROM authors")
cursor.execute("DELETE FROM customers")
cursor.execute("DELETE FROM subjects")
conn.commit()
subjects = [
("Программирование",),
("Базы данных",),
("Фантастика",),
("История",)
]
cursor.executemany("INSERT INTO subjects (subject) VALUES (?)", subjects)
conn.commit()
cursor.execute("SELECT id, subject FROM subjects")
subjects_dict = {row[1]: row[0] for row in cursor.fetchall()}
authors_data = [
("Мартин", "Роберт", "Ц.", 1952),
("Кнут", "Дональд", "Э.", 1938),
("Лукьяненко", "Сергей", "В.", 1968),
("Толстой", "Лев", "Н.", 1828),
]
cursor.executemany('''
INSERT INTO authors (last_name, first_name, patronymic, year_of_birth)
VALUES (?, ?, ?, ?)
''', authors_data)
conn.commit()
cursor.execute("SELECT id, last_name, first_name FROM authors")
authors = []
for row in cursor.fetchall():
authors.append({"id": row[0], "last_name": row[1], "first_name": row[2]})
martin_id = next(a["id"] for a in authors if a["last_name"] == "Мартин")
knuth_id = next(a["id"] for a in authors if a["last_name"] == "Кнут")
luk_id = next(a["id"] for a in authors if a["last_name"] == "Лукьяненко")
tolstoy_id= next(a["id"] for a in authors if a["last_name"] == "Толстой")
cursor.execute("INSERT INTO author_subject (author_id, subject_id) VALUES (?, ?)",
(martin_id, subjects_dict["Программирование"]))
cursor.execute("INSERT INTO author_subject (author_id, subject_id) VALUES (?, ?)",
(martin_id, subjects_dict["Базы данных"]))
cursor.execute("INSERT INTO author_subject (author_id, subject_id) VALUES (?, ?)",
(knuth_id, subjects_dict["Программирование"]))
cursor.execute("INSERT INTO author_subject (author_id, subject_id) VALUES (?, ?)",
(luk_id, subjects_dict["Фантастика"]))
cursor.execute("INSERT INTO author_subject (author_id, subject_id) VALUES (?, ?)",
(tolstoy_id, subjects_dict["История"]))
conn.commit()
books_data = [
("Чистая архитектура", "О проектировании программных систем", 2017,
"Питер", 1, 5, 0, subjects_dict["Программирование"]),
("Искусство программирования, т.1", "Фундаментальный труд", 1968,
"Вильямс", 2, 3, 0, subjects_dict["Программирование"]),
("Дозоры", "Серия городского фэнтези", 1998,
"АСТ", 1, 10, 0, subjects_dict["Фантастика"]),
("Война и мир", "Роман-эпопея", 1869,
"Русский вестник", 3, 8, 0, subjects_dict["История"]),
]
cursor.executemany('''
INSERT INTO books (book_name, annotation, year_of_publication, publisher,
number_of_racks, number_of_books, books_in_use, subject_id)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
''', books_data)
conn.commit()
cursor.execute("SELECT id, book_name FROM books")
books = {row[1]: row[0] for row in cursor.fetchall()}
book_author_data = [
(books["Чистая архитектура"], martin_id),
(books["Искусство программирования, т.1"], knuth_id),
(books["Дозоры"], luk_id),
(books["Война и мир"], tolstoy_id),
]
cursor.executemany("INSERT INTO book_author (book_id, author_id) VALUES (?, ?)", book_author_data)
conn.commit()
customers_data = [
("Иванов", "Иван", "Иванович", "1990-05-12", "+7 123 456-78-90", "ул. Пушкина, д.10"),
("Петрова", "Анна", "Сергеевна", "1985-08-24", "+7 987 654-32-10", "пр. Ленина, 5"),
]
cursor.executemany('''
INSERT INTO customers (last_name, first_name, patronymic, date_of_birth, phone_number, home_address)
VALUES (?, ?, ?, ?, ?, ?)
''', customers_data)
conn.commit()
cursor.execute("SELECT id, last_name FROM customers")
customers = {row[1]: row[0] for row in cursor.fetchall()}
today = date.today()
borrows_data = [
(books["Чистая архитектура"], customers["Иванов"], today - timedelta(days=5), None), # не вернули
(books["Искусство программирования, т.1"], customers["Петрова"], today - timedelta(days=2), today + timedelta(days=12)),
(books["Дозоры"], customers["Иванов"], today - timedelta(days=30), today - timedelta(days=5)), # уже вернул
]
cursor.executemany('''
INSERT INTO borrows (book_id, customer_id, date_of_issue, return_date)
VALUES (?, ?, ?, ?)
''', borrows_data)
conn.commit()
cursor.execute('''
UPDATE books SET books_in_use = (
SELECT COUNT(*) FROM borrows
WHERE borrows.book_id = books.id AND borrows.return_date IS NULL
)
''')
conn.commit()
print("✅ Тестовые данные добавлены.")
def example_queries(conn):
cursor = conn.cursor()
print("\n1. Все книги с авторами и тематиками:")
cursor.execute('''
SELECT b.book_name,
GROUP_CONCAT(a.last_name || ' ' || a.first_name, ', ') AS authors,
s.subject
FROM books b
LEFT JOIN book_author ba ON b.id = ba.book_id
LEFT JOIN authors a ON ba.author_id = a.id
LEFT JOIN subjects s ON b.subject_id = s.id
GROUP BY b.id
ORDER BY b.book_name
''')
for row in cursor.fetchall():
print(f" {row[0]} | Авторы: {row[1] if row[1] else '—'} | Тема: {row[2]}")
print("\n2. Читатели и книги, которые они не вернули:")
cursor.execute('''
SELECT c.last_name || ' ' || c.first_name AS reader,
GROUP_CONCAT(b.book_name, ', ') AS books_on_hand
FROM customers c
JOIN borrows br ON c.id = br.customer_id
JOIN books b ON br.book_id = b.id
WHERE br.return_date IS NULL
GROUP BY c.id
''')
rows = cursor.fetchall()
if rows:
for row in rows:
print(f" {row[0]}: {row[1]}")
else:
print(" (нет читателей с книгами на руках)")
print("\n3. Книги, у которых истёк срок возврата (если return_date уже прошла, но книга не возвращена):")
today_str = date.today().isoformat()
cursor.execute('''
SELECT b.book_name, c.last_name || ' ' || c.first_name AS reader,
br.return_date
FROM borrows br
JOIN books b ON br.book_id = b.id
JOIN customers c ON br.customer_id = c.id
WHERE br.return_date IS NOT NULL
AND br.return_date < ?
AND br.return_date NOT NULL
''', (today_str,))
overdue = cursor.fetchall()
if overdue:
for row in overdue:
print(f" {row[0]} | Читатель: {row[1]} | срок был {row[2]}")
else:
print(" (просроченных нет)")
print("\n 4. Статистика: количество экземпляров книг по тематикам:")
cursor.execute('''
SELECT s.subject, SUM(b.number_of_books) AS total_books
FROM subjects s
LEFT JOIN books b ON s.id = b.subject_id
GROUP BY s.id
ORDER BY total_books DESC
''')
for row in cursor.fetchall():
print(f" {row[0]}: {row[1] if row[1] else 0} экз.")
print("\n 5. Топ-3 автора по количеству книг в каталоге:")
cursor.execute('''
SELECT a.last_name, a.first_name, COUNT(b.id) AS book_count
FROM authors a
LEFT JOIN book_author ba ON a.id = ba.author_id
LEFT JOIN books b ON ba.book_id = b.id
GROUP BY a.id
ORDER BY book_count DESC
LIMIT 3
''')
for row in cursor.fetchall():
print(f" {row[0]} {row[1]} — {row[2]} книг")
def main():
conn = sqlite3.connect("library.db")
conn.row_factory = sqlite3.Row
try:
create_tables(conn)
insert_test_data(conn)
example_queries(conn)
except Exception as e:
print("Ошибка:", e)
conn.rollback()
finally:
conn.close()
print("\n Работа завершена. База данных 'library.db' сохранена.")
if __name__ == "__main__":
main()