Λύσεις — Κεφάλαιο 10: Βάσεις Δεδομένων (σελ. 187-189) – ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΥΠΟΛΟΓΙΣΤΩΝ Γ΄ ΕΠΑΛ

Λύσεις — Κεφάλαιο 10: Βάσεις Δεδομένων (σελ. 187-189)

Λύσεις της επαναληπτικής Δραστηριότητας (ανάλυση προγράμματος sqlite3), των 6 Ερωτήσεων (ΒΔ trade.db, πίνακας customers) και των 6 Εργαστηριακών ασκήσεων (school.db, πίνακας students) του κεφαλαίου 10.


Δραστηριότητα 1 (επαναληπτική) — Μελέτη και εκτέλεση του προγράμματος με τη ΒΔ example2.db και τον πίνακα users

Ερώτηση: Μελετήστε και εκτελέστε το παρακάτω πρόγραμμα, όπου δημιουργείται η Βάση Δεδομένων example2.db και ο πίνακας users, ο οποίος περιέχει το όνομα, το τηλέφωνο, το mail και το συνθηματικό των χρηστών ενός συστήματος. (import sqlite3 / conn = sqlite3.connect('example2.db') / cursor = conn.cursor() / cursor.execute(CREATE TABLE IF NOT EXISTS users(id INTEGER PRIMARY KEY, name TEXT, phone TEXT, email TEXT unique, password TEXT)) / conn.commit() / conn.close() / db = sqlite3.connect('example2.db') / cursor = db.cursor() / … / cursor.execute(INSERT INTO users(name, phone, email, password) VALUES(?,?,?,?), (name1, phone1, email1, password1)) / print 'First user inserted' / … / db.commit())

Απάντηση:

  • Τι κάνει το πρόγραμμα, βήμα-βήμα:import sqlite3 — εισαγωγή της βιβλιοθήκης. ② conn = sqlite3.connect('example2.db')σύνδεση με τη ΒΔ· επειδή το αρχείο δεν υπάρχει, δημιουργείται νέα (κενή) ΒΔ στον τρέχοντα φάκελο. ③ cursor = conn.cursor() — αντικείμενο cursor για την εκτέλεση εντολών SQL. ④ CREATE TABLE IF NOT EXISTS users(...) — δημιουργεί τον πίνακα users με πέντε πεδία: id INTEGER PRIMARY KEY (πρωτεύον κλειδί, συμπληρώνεται αυτόματα με αύξοντα αριθμό), name, phone, email TEXT unique, password TEXT. Το IF NOT EXISTS αποτρέπει σφάλμα αν ο πίνακας υπάρχει ήδη (π.χ. σε δεύτερη εκτέλεση). ⑤ conn.commit()καταχώρηση της δομής στο αρχείο· ⑥ conn.close() — κλείσιμο της πρώτης σύνδεσης.
  • db = sqlite3.connect('example2.db') και cursor = db.cursor()νέα σύνδεση με την ίδια ΒΔ (τώρα το αρχείο υπάρχει) και νέος cursor. ⑧ Ορίζονται οι μεταβλητές name1, phone1, email1, password1 (Panagiotis, 2105666858, [email protected], 12345) και name2… (Ioannis, 2105657241, [email protected], abcdef). ⑨ cursor.execute('INSERT INTO users(name, phone, email, password) VALUES(?,?,?,?)', (name1, phone1, email1, password1))εισαγωγή εγγραφής με την τεχνική υποκατάστασης με ερωτηματικά: τα τέσσερα ? αντικαθίστανται διαδοχικά από τις τιμές της πλειάδας που δίνεται ως δεύτερο όρισμα της execute· το id δεν δίνεται — το συμπληρώνει η ΒΔ (1). Τυπώνεται «First user inserted». ⑩ Ομοίως η δεύτερη εισαγωγή (id 2) και «Second user inserted». ⑪ db.commit()οριστική καταχώρηση των δύο εγγραφών στο αρχείο (μέχρι τότε ήταν στη μνήμη).
  • Αποτέλεσμα (επαληθευμένο με εκτέλεση): ο πίνακας users περιέχει (1, 'Panagiotis', '2105666858', '[email protected]', '12345') και (2, 'Ioannis', '2105657241', '[email protected]', 'abcdef') — ελέγχεται με cursor.execute('SELECT * FROM users'); print cursor.fetchall(). Στην οθόνη εμφανίζονται μόνο τα δύο μηνύματα print.
  • Παρατήρηση για το unique: η δήλωση email TEXT unique επιβάλλει κάθε email να είναι διαφορετικό· αν εκτελέσουμε το πρόγραμμα δεύτερη φορά (ή προσπαθήσουμε να εισάγουμε χρήστη με υπάρχον email), η INSERT αποτυγχάνει με σφάλμα sqlite3.IntegrityError: UNIQUE constraint failed: users.email — ο πίνακας όμως δεν ξαναδημιουργείται χάρη στο IF NOT EXISTS. Επίσης: το πρόγραμμα δεν κλείνει τη δεύτερη σύνδεση — καλό είναι να προστεθούν cursor.close() και db.close(). Η υποκατάσταση με ? είναι ασφαλέστερη από τη συνένωση συμβολοσειρών (αποφυγή SQL injection) και χειρίζεται σωστά τα εισαγωγικά μέσα στις τιμές.

Σύνοψη: Δημιουργία/σύνδεση με example2.db, cursor, CREATE TABLE IF NOT EXISTS users (id PRIMARY KEY αυτόματο, email unique), commit/close· νέα σύνδεση, δύο INSERT με υποκατάσταση ? από πλειάδες (id αυτόματα 1, 2), μηνύματα print, commit· επανεκτέλεση → σφάλμα UNIQUE στο email.

Κριτήρια αξιολόγησης:

  • Ρόλος κάθε τμήματος (IF NOT EXISTS, PRIMARY KEY, unique, ?, commit) + τελικό περιεχόμενο πίνακα.

Ερώτηση 1 — Πώς εισάγονται εντολές της sqlite3 σε κώδικα Python

Ερώτηση: Πώς εισάγονται εντολές της sqlite3 μέσα σε κώδικα Python;

Απάντηση:

  • ① Στην αρχή του προγράμματος εισάγουμε τη βιβλιοθήκη με τη δήλωση import sqlite3 (σελ. 177). ② Δημιουργούμε σύνδεση με τη ΒΔ: conn = sqlite3.connect('όνομα.db') και ένα αντικείμενο cursor: curs = conn.cursor(). ③ Κάθε εντολή SQL γράφεται ως συμβολοσειρά (σε απλά ή τριπλά εισαγωγικά αν πιάνει πολλές γραμμές) και εκτελείται με τη μέθοδο curs.execute('εντολή SQL') — π.χ. curs.execute('SELECT * FROM cars')· για πολλές εγγραφές μαζί curs.executemany('INSERT … VALUES (?,?,…)', λίστα), όπου τα ερωτηματικά υποκαθίστανται από τις τιμές. Πεζά/κεφαλαία στις εντολές SQL είναι αδιάφορα (γράφονται κεφαλαία για διάκριση).
  • ④ Οι αλλαγές (INSERT/UPDATE/DELETE) καταχωρούνται στο αρχείο με conn.commit()· τα αποτελέσματα μιας SELECT διαβάζονται με curs.fetchall() / fetchone() ή με for row in curs.execute(...). ⑤ Στο τέλος curs.close() και conn.close().

Σύνοψη: (ενδεικτική) import sqlite3 → conn = sqlite3.connect(...) → curs = conn.cursor() → η εντολή SQL ως συμβολοσειρά μέσα στην curs.execute('…') (ή executemany με ?) → conn.commit() για αλλαγές, fetchall() για SELECT → close().

Κριτήρια αξιολόγησης:

  • import + execute με συμβολοσειρά SQL + commit.

Ερώτηση 2 — Δημιουργία κενής ΒΔ trade.db

Ερώτηση: Με ποια εντολή μπορούμε να δημιουργήσουμε μια κενή βάση δεδομένων με όνομα trade.db;

Απάντηση:

  • Με την εντολή conn = sqlite3.connect('trade.db') (αφού προηγηθεί import sqlite3). Η connect δημιουργεί αντικείμενο χειριστή σύνδεσης με το αρχείο trade.db· αν το αρχείο δεν υπάρχει, δημιουργείται νέα, κενή βάση δεδομένων με αυτό το όνομα στον φάκελο της Python (σελ. 177). Για άλλον φάκελο δίνουμε τη διαδρομή, π.χ. sqlite3.connect('c:/SQL/trade.db').
  • import sqlite3
    conn = sqlite3.connect('trade.db')     # δημιουργεί την κενή ΒΔ trade.db (αν δεν υπάρχει)
    curs = conn.cursor()                   # cursor για τις επόμενες εντολές

Σύνοψη: import sqlite3· conn = sqlite3.connect('trade.db') — αν δεν υπάρχει το αρχείο, δημιουργείται νέα κενή ΒΔ.

Κριτήρια αξιολόγησης:

  • Η connect + ότι δημιουργεί το αρχείο αν λείπει.

Ερώτηση 3 — Δημιουργία πίνακα customers (AFM, Name, City, Phone) στην trade.db

Ερώτηση: Με ποιες εντολές κώδικα μπορούμε να δημιουργήσουμε έναν πίνακα customers με στοιχεία το AFM, Name, City και Phone στη ΒΔ trade.db;

Απάντηση:

  • Σύνδεση με τη ΒΔ, cursor, και CREATE TABLE με τα τέσσερα πεδία. Το ΑΦΜ είναι μοναδικό για κάθε πελάτη, άρα το ορίζουμε πρωτεύον κλειδί· το δηλώνουμε TEXT (όπως και το τηλέφωνο), γιατί μπορεί να αρχίζει από 0 (π.χ. 012231212) και δεν γίνονται αριθμητικές πράξεις με αυτό:
  • import sqlite3
    conn = sqlite3.connect('trade.db')
    curs = conn.cursor()
    curs.execute('''CREATE TABLE customers
                    (AFM TEXT PRIMARY KEY not null,
                     Name TEXT,
                     City TEXT,
                     Phone TEXT)''')
    conn.commit()
  • Εναλλακτικά με CREATE TABLE IF NOT EXISTS customers (...) ώστε να μην προκύπτει σφάλμα σε επανεκτέλεση, ή με επιπλέον πεδίο id INTEGER PRIMARY KEY ως αύξοντα αριθμό και το AFM απλώς unique. Επαληθεύτηκε με εκτέλεση.

Σύνοψη: conn = sqlite3.connect('trade.db')· curs = conn.cursor()· curs.execute(CREATE TABLE customers (AFM TEXT PRIMARY KEY, Name TEXT, City TEXT, Phone TEXT))· conn.commit().

Κριτήρια αξιολόγησης:

  • Σωστή σύνταξη CREATE TABLE με τύπους + κλειδί.

Ερώτηση 4 — Εισαγωγή του πελάτη Dimou Manolis

Ερώτηση: Με ποια εντολή μπορούμε να εισάγουμε στον πίνακα customers τον πελάτη με στοιχεία 012231212, Dimou Manolis, Athens, 212456789120;

Απάντηση:

  • Με την εντολή INSERT INTO … VALUES (σελ. 179), δίνοντας τις τιμές με τη σειρά των πεδίων του πίνακα (AFM, Name, City, Phone) — οι τιμές TEXT σε μονά εισαγωγικά — και κατόπιν commit:
  • curs.execute("INSERT INTO customers VALUES ('012231212', 'Dimou Manolis', 'Athens', '212456789120')")
    conn.commit()
  • Ισοδύναμα με ρητή αναφορά των πεδίων ή με υποκατάσταση ερωτηματικών: curs.execute('INSERT INTO customers (AFM, Name, City, Phone) VALUES (?,?,?,?)', ('012231212', 'Dimou Manolis', 'Athens', '212456789120')). Χωρίς το commit η εγγραφή μένει μόνο στη μνήμη.

Σύνοψη: curs.execute(INSERT INTO customers VALUES ('012231212', 'Dimou Manolis', 'Athens', '212456789120'))· conn.commit().

Κριτήρια αξιολόγησης:

  • Σωστή INSERT με τις 4 τιμές σε εισαγωγικά + commit.

Ερώτηση 5 — Εισαγωγή του πελάτη Gatos Nikos και αλλαγή της πόλης του σε Larisa

Ερώτηση: Να εισαχθεί επιπλέον ο πελάτης 0123456789, Gatos Nikos, Athens, 212923876543. Επίσης να τροποποιηθεί η πόλη (city) του πελάτη Gatos σε Larisa.

Απάντηση:

  • Δεύτερη INSERT και μετά UPDATE … SET … WHERE (σελ. 181-182) για την αλλαγή της πόλης — η συνθήκη WHERE εντοπίζει τον συγκεκριμένο πελάτη (με το ΑΦΜ, που είναι το κλειδί, ή με το όνομα):
  • curs.execute("INSERT INTO customers VALUES ('0123456789', 'Gatos Nikos', 'Athens', '212923876543')")
    curs.execute("UPDATE customers SET City = 'Larisa' WHERE AFM = '0123456789'")
    conn.commit()
  • Εναλλακτικά WHERE Name = 'Gatos Nikos'WHERE Name LIKE 'Gatos%'). Μετά τις εντολές ο πίνακας περιέχει: ('012231212', 'Dimou Manolis', 'Athens', …) και ('0123456789', 'Gatos Nikos', 'Larisa', …) — επαληθεύτηκε με SELECT * FROM customers. Χωρίς WHERE η UPDATE θα άλλαζε την πόλη όλων των πελατών.

Σύνοψη: INSERT INTO customers VALUES ('0123456789', 'Gatos Nikos', 'Athens', '212923876543')· UPDATE customers SET City = 'Larisa' WHERE AFM = '0123456789' (ή Name = 'Gatos Nikos')· commit.

Κριτήρια αξιολόγησης:

  • INSERT + UPDATE με WHERE + commit.

Ερώτηση 6 — Διαγραφή όλων των πελατών με πόλη Athens

Ερώτηση: Να διαγραφούν όλοι οι πελάτες που ως πόλη (city) έχουν την τιμή Athens.

Απάντηση:

  • Με την εντολή DELETE FROM … WHERE (σελ. 182-183)· η συνθήκη επιλέγει όλες τις εγγραφές με City = 'Athens':
  • curs.execute("DELETE FROM customers WHERE City = 'Athens'")
    conn.commit()
  • Μετά την εκτέλεση απομένει μόνο ο Gatos Nikos (Larisa) — επαληθεύτηκε. Προσοχή: η διαγραφή είναι εύκολη και μη αναστρέψιμη· χωρίς WHERE η DELETE FROM customers θα διέγραφε όλες τις εγγραφές (ο πίνακας θα έμενε κενός αλλά θα υπήρχε — αντίθετα η DROP TABLE customers διαγράφει τον ίδιο τον πίνακα). Καλό είναι πριν τη διαγραφή να ελέγχουμε τι θα διαγραφεί με SELECT * FROM customers WHERE City = 'Athens'.

Σύνοψη: DELETE FROM customers WHERE City = 'Athens'· conn.commit() — μένει μόνο ο Gatos (Larisa).

Κριτήρια αξιολόγησης:

  • DELETE με WHERE + commit + προσοχή.

Εργαστηριακή άσκηση 1 — Δημιουργία της ΒΔ school.db

Ερώτηση: Δημιουργήστε μια βάση δεδομένων με όνομα school.db.

Απάντηση:

  • import sqlite3
    conn = sqlite3.connect('school.db')   # δημιουργεί το αρχείο school.db (κενή ΒΔ) αν δεν υπάρχει
    curs = conn.cursor()
  • Η connect δημιουργεί το αρχείο school.db στον τρέχοντα φάκελο (ή στη διαδρομή που δίνουμε) και επιστρέφει το αντικείμενο σύνδεσης· ο cursor θα χρησιμοποιηθεί σε όλες τις επόμενες ασκήσεις. Η ΒΔ είναι κενή μέχρι να δημιουργήσουμε πίνακες.

Σύνοψη: import sqlite3· conn = sqlite3.connect('school.db')· curs = conn.cursor().

Κριτήρια αξιολόγησης:

  • connect + cursor.

Εργαστηριακή άσκηση 2 — Πίνακας students με στοιχεία μαθητών

Ερώτηση: Εισάγετε ένα πίνακα με όνομα students, ο οποίος θα περιέχει στοιχεία των μαθητών της τάξης σας, επιλέγοντας εσείς τιμές για το πλήθος και τον τύπο των στοιχείων.

Απάντηση:

  • Επιλέγουμε έξι πεδία: id (αύξων αριθμός, πρωτεύον κλειδί), surname και name (TEXT), address (TEXT), phone (TEXT — μπορεί να αρχίζει από 0/6, δεν είναι αριθμός για πράξεις), grade (μέσος όρος, REAL):
  • curs.execute('''CREATE TABLE IF NOT EXISTS students
                    (id INTEGER PRIMARY KEY,
                     surname TEXT,
                     name TEXT,
                     address TEXT,
                     phone TEXT,
                     grade REAL)''')
    conn.commit()
  • Μπορούν να προστεθούν και άλλα πεδία (ημερομηνία γέννησης TEXT, τμήμα TEXT, απουσίες INTEGER). Το IF NOT EXISTS επιτρέπει επανεκτέλεση του script χωρίς σφάλμα.

Σύνοψη: CREATE TABLE students (id INTEGER PRIMARY KEY, surname TEXT, name TEXT, address TEXT, phone TEXT, grade REAL)· commit.

Κριτήρια αξιολόγησης:

  • Λογική επιλογή πεδίων/τύπων + κλειδί.

Εργαστηριακή άσκηση 3 — Εισαγωγή ενός μαθητή και μετά 9 μαζί

Ερώτηση: Εισάγετε τα στοιχεία ενός μαθητή και στη συνέχεια εισάγετε, όλα μαζί, τα στοιχεία 9 άλλων μαθητών.

Απάντηση:

  • Ένας μαθητής με INSERT … VALUES, οι υπόλοιποι εννέα με λίστα πλειάδων και executemany με έξι ερωτηματικά (σελ. 180):
  • # ένας μαθητής
    curs.execute("INSERT INTO students VALUES (1, 'Papadopoulou', 'Maria', 'Ermou 5', '6971111111', 17.5)")
    # εννέα μαθητές μαζί
    mathites = [(2, 'Nikolaou', 'Giorgos', 'Athinas 10', '6972222222', 15.2),
                (3, 'Dimou', 'Eleni', 'Patision 3', '6973333333', 18.9),
                (4, 'Alexiou', 'Kostas', 'Stadiou 7', '6974444444', 12.4),
                (5, 'Vasileiou', 'Anna', 'Solonos 1', '6975555555', 19.6),
                (6, 'Georgiou', 'Petros', 'Omirou 2', '6976666666', 14.0),
                (7, 'Ioannou', 'Sofia', 'Akadimias 9', '6977777777', 16.3),
                (8, 'Karali', 'Dimitra', 'Kolokotroni 4', '6978888888', 13.7),
                (9, 'Lambrou', 'Nikos', 'Panepistimiou 8', '6979999999', 17.1),
                (10, 'Markou', 'Christina', 'Mitropoleos 6', '6970000000', 18.2)]
    curs.executemany('INSERT INTO students VALUES (?,?,?,?,?,?)', mathites)
    conn.commit()
  • Τα έξι ερωτηματικά αντιστοιχούν στα έξι πεδία και αντικαθίστανται διαδοχικά από τις τιμές κάθε πλειάδας. Αν παραλείψουμε το id (INSERT INTO students (surname, name, …) VALUES (?,?,?,?,?)), η ΒΔ το συμπληρώνει αυτόματα. Το commit καταχωρεί και τις 10 εγγραφές.

Σύνοψη: Μία INSERT … VALUES (…) για τον πρώτο· λίστα 9 πλειάδων + curs.executemany('INSERT INTO students VALUES (?,?,?,?,?,?)', λίστα)· commit.

Κριτήρια αξιολόγησης:

  • INSERT + executemany με σωστό πλήθος ? + commit.

Εργαστηριακή άσκηση 4 — Τροποποίηση στοιχείου μαθητή

Ερώτηση: Τροποποιήστε κάποιο από τα στοιχεία ενός μαθητή, όπως για παράδειγμα τη διεύθυνση ή το τηλέφωνό του.

Απάντηση:

  • # αλλαγή τηλεφώνου του μαθητή με id 4 (Alexiou Kostas)
    curs.execute("UPDATE students SET phone = '6980000000' WHERE id = 4")
    # αλλαγή διεύθυνσης με βάση το επώνυμο
    curs.execute("UPDATE students SET address = 'Ippokratous 12' WHERE surname = 'Dimou'")
    conn.commit()
  • Η UPDATE … SET πεδίο = νέα_τιμή WHERE συνθήκη αλλάζει μόνο τις εγγραφές που ικανοποιούν τη συνθήκη — ασφαλέστερα με το id (πρωτεύον κλειδί, μοναδικό). Μπορούμε να αλλάξουμε πολλά πεδία μαζί: SET phone = '…', address = '…'. Χωρίς WHERE θα άλλαζαν όλοι οι μαθητές. Επαληθεύτηκε με εκτέλεση.

Σύνοψη: UPDATE students SET phone = '6980000000' WHERE id = 4 (ή SET address = … WHERE surname = …)· commit.

Κριτήρια αξιολόγησης:

  • UPDATE με SET και WHERE + commit.

Εργαστηριακή άσκηση 5 — Διαγραφή ενός μαθητή

Ερώτηση: Διαγράψτε ένα μαθητή.

Απάντηση:

  • curs.execute('DELETE FROM students WHERE id = 6')      # διαγραφή του Georgiou Petros
    conn.commit()
  • Η DELETE FROM students WHERE id = 6 αφαιρεί μόνο την εγγραφή με το συγκεκριμένο κλειδί (μένουν 9 μαθητές). Εναλλακτικά WHERE surname = 'Georgiou' AND name = 'Petros'. Προσοχή: χωρίς WHERE διαγράφονται όλες οι εγγραφές· η διαγραφή δεν αναιρείται μετά το commit, γι' αυτό ελέγχουμε πρώτα με SELECT ποια εγγραφή θα διαγραφεί.

Σύνοψη: DELETE FROM students WHERE id = 6· commit — προσοχή στο WHERE.

Κριτήρια αξιολόγησης:

  • DELETE με WHERE + commit.

Εργαστηριακή άσκηση 6 — Εμφάνιση μαθητών ταξινομημένων κατά επίθετο και κατά όνομα

Ερώτηση: Εμφανίστε όλους τους μαθητές ταξινομημένους ως προς το επίθετό τους. Εμφανίστε ξανά όλους τους μαθητές ταξινομημένους ως προς το όνομά τους.

Απάντηση:

  • print 'Μαθητές κατά επώνυμο:'
    for row in curs.execute('SELECT * FROM students ORDER BY surname ASC'):
        print row
    
    print 'Μαθητές κατά όνομα:'
    curs.execute('SELECT * FROM students ORDER BY name')     # ASC είναι η προεπιλογή
    for row in curs.fetchall():
        print row
    
    curs.close()
    conn.close()
  • Η ORDER BY surname ταξινομεί αλφαβητικά κατά επώνυμο (Alexiou, Dimou, Ioannou, Karali, …), η ORDER BY name κατά όνομα (Anna, Christina, Dimitra, …) — επαληθεύτηκε με εκτέλεση. Το ASC μπορεί να παραλειφθεί, το DESC (φθίνουσα) πρέπει να δηλωθεί. Για ταξινόμηση με δεύτερο κριτήριο: ORDER BY surname, name. Οι εγγραφές διαβάζονται είτε με for row in curs.execute(...) είτε με fetchall(). Στο τέλος κλείνουμε cursor και σύνδεση.

Σύνοψη: SELECT FROM students ORDER BY surname (ASC) και SELECT FROM students ORDER BY name· εμφάνιση με for row in … / fetchall()· close.

Κριτήρια αξιολόγησης:

  • Δύο SELECT με ORDER BY + εμφάνιση εγγραφών.

 ΣΧΟΛΙΚΟ ΒΙΒΛΙΟ