Pliki otwieramy w edytorze tekstu, który ma możliwość pokazywania białych znaków – w ten sposób łatwiej nam będzie ustalić, jakim separatorem oddzielone są wartości pól w wierszach.
Rl4sYNqVXV2TY
Ilustracja przedstawia zawartość pliku: uczniowie.csv. Separatorem jest znak tabulacji, czyli pozioma strzałka skierowana w prawo, dane składają się z identyfikatora ucznia, imienia, nazwiska oraz klasy.
Źródło: Contentplus.pl Sp. z o.o., tylko do użytku edukacyjnego.
Na zrzucie widać, że w pliku uczniowie.csv separatorem jest znak tabulacji, a dane składają się z identyfikatora ucznia, imienia i nazwiska oraz klasy.
Instrukcja SQL, która utworzy nam odpowiednią tabelę, może wyglądać następująco:
Przykład 1
Linia 1. DROP TABLE IF EXISTS uczniowie średnik.
Linia 2. CREATE TABLE uczniowie otwórz nawias okrągły.
Linia 3. id CHAR otwórz nawias okrągły 8 zamknij nawias okrągły PRIMARY KEY przecinek.
Linia 4. imie VARCHAR otwórz nawias okrągły 20 zamknij nawias okrągły NOT NULL CHECK otwórz nawias okrągły imie otwórz nawias ostrokątny zamknij nawias ostrokątny apostrof apostrof zamknij nawias okrągły przecinek.
Linia 5. nazwisko VARCHAR otwórz nawias okrągły 30 zamknij nawias okrągły NOT NULL CHECK otwórz nawias okrągły nazwisko otwórz nawias ostrokątny zamknij nawias ostrokątny apostrof apostrof zamknij nawias okrągły przecinek.
Linia 6. klasa CHAR otwórz nawias okrągły 5 zamknij nawias okrągły DEFAULT apostrof apostrof.
Linia 7. zamknij nawias okrągły średnik.
DROP TABLE IF EXISTS uczniowie;
CREATE TABLE uczniowie (
id CHAR(8) PRIMARY KEY,
imie VARCHAR(20) NOT NULL CHECK(imie <> ''),
nazwisko VARCHAR(30) NOT NULL CHECK(nazwisko <> ''),
klasa CHAR(5) DEFAULT ''
);
Na uwagę zasługuję fakt, że identyfikator ucznia, czyli klucz główny tabeli, nie jest liczbą całkowitą, ale 8‑znakowym ciągiem znaków. Ograniczenia nałożone na pola imie i nazwisko nie dopuszczają braku wartości oraz pustych ciągów znaków. Dla pola zdefiniowano wartość domyślną – pusty ciąg znaków.
Klauzula DROP TABLE IF EXISTS usuwa tabelę o podanej nazwie w bazie, jeżeli wcześniej już istniała. Używamy jej, aby można było wielokrotnie, bez przeszkód, testować skrypty.
RXwckbTQk7Pgj
ilustracja przedstawia zawartość pliku: przedmioty.csv. Wiersze zawierają dwie informacje: identyfikator oraz nazwę przedmiotu. Za identyfikatorem będącym liczbą porządkową postawiono przecinek.
Źródło: Contentplus.pl Sp. z o.o., tylko do użytku edukacyjnego.
Separatorem w pliku przedmioty.csv jest przecinek, wiersze zawierają tylko dwie informacje: identyfikator oraz nazwę przedmiotu. Dla tych danych utworzymy prostą tabelę słownikowątabela słownikowatabelę słownikową, za pomocą polecenia:
Przykład 2
Linia 1. DROP TABLE IF EXISTS przedmioty średnik.
Linia 2. CREATE TABLE przedmioty otwórz nawias okrągły.
Linia 3. id INTEGER PRIMARY KEY AUTOINCREMENT przecinek.
Linia 4. nazwa VARCHAR otwórz nawias okrągły 60 zamknij nawias okrągły NOT NULL CHECK otwórz nawias okrągły nazwa otwórz nawias ostrokątny zamknij nawias ostrokątny apostrof apostrof zamknij nawias okrągły.
Linia 5. zamknij nawias okrągły średnik.
DROP TABLE IF EXISTS przedmioty;
CREATE TABLE przedmioty (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nazwa VARCHAR(60) NOT NULL CHECK(nazwa <> '')
);
RAYJNWc7Ghxzu
Ilustracja przedstawia zawartość pliku: oceny.csv. Separatorem danych jest znak tabulacji, czyli pozioma strzałka skierowana w prawo. Plik zawiera następujące informacje: identyfikator oceny, datę otrzymania, identyfikator ucznia, identyfikator przedmiotu oraz ocenę.
Źródło: Contentplus.pl Sp. z o.o., tylko do użytku edukacyjnego.
W pliku oceny.csv separatorem danych ponownie jest znak tabulacji, plik zawiera następujące informacje: identyfikator oceny, datę otrzymania, identyfikator ucznia, identyfikator przedmiotu oraz ocenę. Z tego wynika, że odpowiednia klauzula SQL powinna utworzyć nie tylko pola do przechowywania danych, ale również relacje łączące tabelę ocen z tabelami uczniowie i przedmioty.
Przykład 3
Linia 1. DROP TABLE IF EXISTS oceny średnik.
Linia 2. CREATE TABLE oceny otwórz nawias okrągły.
Linia 3. id INTEGER PRIMARY KEY AUTOINCREMENT przecinek.
Linia 4. data DATE NOT NULL przecinek.
Linia 5. id podkreślnik ucznia CHAR otwórz nawias okrągły 8 zamknij nawias okrągły NOT NULL przecinek.
Linia 6. id podkreślnik przedm INTEGER przecinek.
Linia 7. ocena DECIMAL otwórz nawias okrągły 3 przecinek 2 zamknij nawias okrągły NOT NULL CHECK otwórz nawias okrągły ocena otwórz nawias ostrokątny 7 zamknij nawias okrągły przecinek.
Linia 8. FOREIGN KEY otwórz nawias okrągły id podkreślnik ucznia zamknij nawias okrągły REFERENCES uczniowie otwórz nawias okrągły id zamknij nawias okrągły.
Linia 9. ON DELETE CASCADE przecinek.
Linia 10. FOREIGN KEY otwórz nawias okrągły id podkreślnik przedm zamknij nawias okrągły REFERENCES przedmioty otwórz nawias okrągły id zamknij nawias okrągły.
Linia 11. ON DELETE SET NULL.
Linia 12. zamknij nawias okrągły średnik.
DROP TABLE IF EXISTS oceny;
CREATE TABLE oceny (
id INTEGER PRIMARY KEY AUTOINCREMENT,
data DATE NOT NULL,
id_ucznia CHAR(8) NOT NULL,
id_przedm INTEGER,
ocena DECIMAL(3,2) NOT NULL CHECK(ocena < 7),
FOREIGN KEY (id_ucznia) REFERENCES uczniowie(id)
ON DELETE CASCADE,
FOREIGN KEY (id_przedm) REFERENCES przedmioty(id)
ON DELETE SET NULL
);
Definiując pola, w których przechowywane będą wartości z innych tabel, to znaczy id_ucznia oraz id_przedm, pamiętać musimy, aby miały takie same typy danych, jak odpowiadające im pola w tabelach źródłowych.
Do tworzenia relacji używamy klauzul FOREIGN KEY...REFERENCES... umieszczonych na końcu definicji pól. W nawiasach okrągłych podajemy nazwę klucza obcego, a następnie nazwę tabeli źródłowej i klucza głównego w nawiasach okrągłych.
Na koniec wszystkie podane klauzule zapisujemy w pliku uczniowie.sql, w katalogu o nazwie uczniowie_baza.
Tworzenie bazy i tabel w języku Python
Język Python ułatwia obsługę baz danych dzięki standardowym modułom, takim jak np. sqlite3 czy mysql. Zacznijmy od kodu, który umożliwi nawiązanie połączenia z bazą oraz wykonywanie na niej operacji. W pliku uczniowie.py, który umieszczamy w katalogu uczniowie_baza, wpisujemy początkowy kod:
Przykład 4
Linia 1. import sqlite3 przecinek os.
Linia 4. def main otwórz nawias okrągły args zamknij nawias okrągły dwukropek.
Linia 5. baza znak równości apostrof uczniowie kropka db apostrof.
Linia 6. con znak równości sqlite3 kropka connect otwórz nawias okrągły baza zamknij nawias okrągły kratka połączenie z bazą.
Linia 7. cur znak równości con kropka cursor otwórz nawias okrągły zamknij nawias okrągły kratka utworzenie obiektu kursora.
Linia 9. utworz podkreślnik tabele otwórz nawias okrągły con przecinek apostrof uczniowie kropka sql apostrof zamknij nawias okrągły kratka tworzenie tabel.
Linia 10. zbadaj podkreślnik baze otwórz nawias okrągły cur zamknij nawias okrągły kratka sprawdzenie schematu bazy.
Linia 12. con kropka commit otwórz nawias okrągły zamknij nawias okrągły kratka zatwierdzenie zmian w bazie.
Linia 13. con kropka close otwórz nawias okrągły zamknij nawias okrągły kratka zamknięcie połączenia z bazą.
Linia 14. return 0.
Linia 17. if podkreślnik podkreślnik name podkreślnik podkreślnik znak równości znak równości apostrof podkreślnik podkreślnik main podkreślnik podkreślnik apostrof dwukropek.
Linia 18. import sys.
Linia 19. sys kropka exit otwórz nawias okrągły main otwórz nawias okrągły sys kropka argv zamknij nawias okrągły zamknij nawias okrągły.
import sqlite3, os
def main(args):
baza = 'uczniowie.db'
con = sqlite3.connect(baza) # połączenie z bazą
cur = con.cursor() # utworzenie obiektu kursora
utworz_tabele(con, 'uczniowie.sql') # tworzenie tabel
zbadaj_baze(cur) # sprawdzenie schematu bazy
con.commit() # zatwierdzenie zmian w bazie
con.close() # zamknięcie połączenia z bazą
return 0
if __name__ == '__main__':
import sys
sys.exit(main(sys.argv))
Baza danych SQLite3 zawarta jest w jednym pliku o nazwie uczniowie.db. Metoda connect() łączy się z bazą i zwraca obiekt połączenia. Ma on następujące metody:
cursor() – tworzy obiekt kursorakursorkursora, który pozwala na wykonywanie zapytań i odczytywanie ich wyników,
commit() – zatwierdza zmiany w bazie,
close() – zamyka połączenie z bazą.
W funkcji głównej umieściliśmy wywołanie funkcji utworz_tabele() oraz zbadaj_baze(), których kod (przedstawiony w Przykładzie 5) umieszczamy przed funkcją główną.
Przykład 5
Linia 1. def zbadaj podkreślnik baze otwórz nawias okrągły cur zamknij nawias okrągły dwukropek.
Linia 2. cur kropka execute otwórz nawias okrągły cudzysłów SELECT asterysk FROM sqlite podkreślnik master średnik cudzysłów zamknij nawias okrągły.
Linia 3. for t in cur kropka fetchall otwórz nawias okrągły zamknij nawias okrągły dwukropek.
Linia 4. print otwórz nawias okrągły t otwórz nawias kwadratowy 4 zamknij nawias kwadratowy zamknij nawias okrągły.
Linia 7. def utworz podkreślnik tabele otwórz nawias okrągły cur przecinek plik podkreślnik sql zamknij nawias okrągły dwukropek.
Linia 8. if os kropka path kropka isfile otwórz nawias okrągły plik podkreślnik sql zamknij nawias okrągły dwukropek.
Linia 9. with open otwórz nawias okrągły plik podkreślnik sql przecinek newline znak równości apostrof apostrof przecinek encoding znak równości apostrof utf minus 8 apostrof zamknij nawias okrągły as sql dwukropek.
Linia 10. cur kropka executescript otwórz nawias okrągły sql kropka read otwórz nawias okrągły zamknij nawias okrągły zamknij nawias okrągły.
Linia 11. else dwukropek.
Linia 12. print otwórz nawias okrągły cudzysłów Brak pliku SQL na dysku wykrzyknik cudzysłów zamknij nawias okrągły.
def zbadaj_baze(cur):
cur.execute("SELECT * FROM sqlite_master;")
for t in cur.fetchall():
print(t[4])
def utworz_tabele(cur, plik_sql):
if os.path.isfile(plik_sql):
with open(plik_sql, newline='', encoding='utf-8') as sql:
cur.executescript(sql.read())
else:
print("Brak pliku SQL na dysku!")
W funkcji utworz_tabele() sprawdzamy, czy podany plik zawierający instrukcje SQL istnieje na dysku i jeżeli tak, otwieramy go przy użyciu instrukcji with open() as, dzięki czemu zostanie on automatycznie zamknięty. Treść pliku odczytujemy za pomocą metody read(), która zwraca ciąg znaków, w tym wypadku polecenia SQL. Ostatecznie przekazujemy je do wykonania metodzie executescript().
Zadaniem funkcji zbadaj_baze() jest odczytanie wewnętrznej tabeli bazy SQLite3 o nazwie sqlite_master, która przechowuje schemat bazy. Jeżeli po wykonaniu skryptu zobaczymy klauzule SQL, które posłużyły do utworzenia tabel, będzie to znaczyło, że baza utworzona została poprawnie.
Ćwiczenie 1
Przetestuj działanie przygotowanego skryptu, uruchamiając go w wierszu poleceń lub z poziomu wybranego edytora. Skrypt możesz uruchamiać wielokrotnie, aby wyeliminować ewentualne błędy.
Poprawnym wynikiem działania skryptu jest wyświetlenie w wierszu poleceń instrukcji SQL, które posłużyły do utworzenia tabel, a także obecność pliku uczniowie.db w katalogu uczniowie_baza.
Dodawanie danych w języku Python
Do wprowadzenia danych wykorzystamy podane na wstępie pliki w formacie CSVformat CSVw formacie CSV oraz drugi skrypt języka Python. W katalogu z poprzednimi plikami zapisujemy plik o nazwie uczniowie_dane.py, którego początkowa zawartość jest identyczna jak w poprzednim skrypcie, poza dodatkowym importem oraz wywoływaną funkcją.
Przykład 6
Linia 1. import sqlite3.
Linia 2. import os.
Linia 3. import csv.
Linia 6. def dodaj podkreślnik dane otwórz nawias okrągły cur przecinek tabela przecinek sep zamknij nawias okrągły dwukropek.
Linia 7. plik podkreślnik csv znak równości tabela plus apostrof kropka csv apostrof.
Linia 8. if not os kropka path kropka isfile otwórz nawias okrągły plik podkreślnik csv zamknij nawias okrągły dwukropek.
Linia 9. print otwórz nawias okrągły f cudzysłów Brak pliku otwórz nawias klamrowy plik podkreślnik csv zamknij nawias klamrowy na dysku wykrzyknik cudzysłów zamknij nawias okrągły.
Linia 10. return False.
Linia 12. dane znak równości otwórz nawias kwadratowy zamknij nawias kwadratowy kratka lista rekordów.
Linia 13. with open otwórz nawias okrągły plik podkreślnik csv przecinek newline znak równości apostrof apostrof przecinek encoding znak równości apostrof utf minus 8 apostrof zamknij nawias okrągły as plik dwukropek dwukropek.
Linia 14. for wiersz in csv kropka reader otwórz nawias okrągły plik przecinek delimiter znak równości sep zamknij nawias okrągły dwukropek.
Linia 15. dane kropka append otwórz nawias okrągły wiersz zamknij nawias okrągły.
Linia 16. for rekord in dane dwukropek.
Linia 17. print otwórz nawias okrągły rekord zamknij nawias okrągły.
Linia 20. def main otwórz nawias okrągły args zamknij nawias okrągły dwukropek.
Linia 21. baza znak równości apostrof uczniowie kropka db apostrof.
Linia 22. con znak równości sqlite3 kropka connect otwórz nawias okrągły baza zamknij nawias okrągły kratka połączenie z bazą.
Linia 23. cur znak równości con kropka cursor otwórz nawias okrągły zamknij nawias okrągły kratka utworzenie obiektu kursora.
Linia 25. dodaj podkreślnik dane otwórz nawias okrągły cur przecinek apostrof uczniowie apostrof przecinek apostrof lewy ukośnik t apostrof zamknij nawias okrągły kratka dodawanie danych.
Linia 27. con kropka commit otwórz nawias okrągły zamknij nawias okrągły kratka zatwierdzenie zmian w bazie.
Linia 28. con kropka close otwórz nawias okrągły zamknij nawias okrągły kratka zamknięcie połączenia z bazą.
Linia 29. return 0.
Linia 32. if podkreślnik podkreślnik name podkreślnik podkreślnik znak równości znak równości apostrof podkreślnik podkreślnik main podkreślnik podkreślnik apostrof dwukropek.
Linia 33. import sys.
Linia 34. sys kropka exit otwórz nawias okrągły main otwórz nawias okrągły sys kropka argv zamknij nawias okrągły zamknij nawias okrągły.
import sqlite3
import os
import csv
def dodaj_dane(cur, tabela, sep):
plik_csv = tabela + '.csv'
if not os.path.isfile(plik_csv):
print(f"Brak pliku {plik_csv} na dysku!")
return False
dane = [] # lista rekordów
with open(plik_csv, newline='', encoding='utf-8') as plik::
for wiersz in csv.reader(plik, delimiter=sep):
dane.append(wiersz)
for rekord in dane:
print(rekord)
def main(args):
baza = 'uczniowie.db'
con = sqlite3.connect(baza) # połączenie z bazą
cur = con.cursor() # utworzenie obiektu kursora
dodaj_dane(cur, 'uczniowie', '\t') # dodawanie danych
con.commit() # zatwierdzenie zmian w bazie
con.close() # zamknięcie połączenia z bazą
return 0
if __name__ == '__main__':
import sys
sys.exit(main(sys.argv))
Funkcja dodaj_dane() otrzymuje jako argumenty kursor, nazwę tabeli i separator danych. Na początku funkcji tworzymy nazwę pliku z danymi, dodając do nazwy tabeli rozszerzenie .csv. Jeżeli pliku nie ma na dysku, wypisujemy komunikat o jego braku, w przeciwnym razie otwieramy plik, używając wspominanej instrukcji with open() as.
Do obsługi plików CSV Python dysponuje dedykowanym modułem csv, który zaimportowaliśmy na początku pliku. Funkcja reader() rozbija na części każdy przeczytany wiersz pliku, używając podanego separatora. Części zwraca jako listę wartości dla danego rekordu. Kolejne rekordy zapisujemy w liście dane. Na końcu w pętli drukujemy zapisane rekordy.
Ćwiczenie 2
Uruchom skrypt, zwróć uwagę na wypisane listy wartości.
Zrzuty pokazują wyniki działania skryptu uruchomionego w terminalu systemu Linux i w wierszu poleceń systemu Windows.
R1819iybNQRM4
Ilustracja przedstawia wynik działania skryptu: uczniowie.dane.py uruchomionego w terminalu systemu Linux. W górnej części okna są zakładki: Plik, Edycja, Widok, Wyszukiwanie, Terminal, Pomoc. W wierszach są dane: identyfikator, imię, nazwisko, klasa. Pomiędzy kolejnymi danymi wstawiono przecinki. Każdy wiersz zaczyna się i kończy nawiasem kwadratowym. Wiersze są na szarym tle.
RCBQKj3B4KDoa
Ilustracja przedstawia wynik działania skryptu: uczniowie.dane.py uruchomionego w wierszu poleceń systemu Windows. W górnej części okna jest pole o nazwie: Wiersz polecenia. W wierszach są dane: identyfikator, imię, nazwisko, klasa. Pomiędzy kolejnymi danymi wstawiono przecinki. Każdy wiersz zaczyna się i kończy nawiasem kwadratowym. Wiersze są na czarnym tle.
Obiekt kursora oferuje kilka metod pozwalających dodawać dane do tabel. Zacznijmy od najprostszej wersji:
Przykład 7
Linia 1. cur kropka execute otwórz nawias okrągły cudzysłów INSERT INTO uczniowie VALUES otwórz nawias okrągły apostrof 123 prawy ukośnik 2011 apostrof przecinek apostrof Wojciech apostrof przecinek apostrof Banasik apostrof przecinek apostrof IV E apostrof zamknij nawias okrągły cudzysłów zamknij nawias okrągły.
cur.execute("INSERT INTO uczniowie VALUES ('123/2011', 'Wojciech', 'Banasik', 'IV E')")
Metoda execute() pozwala wykonać jedno zapytanie SQL na raz. W przedstawionej wersji wartości pól zostały podane bezpośrednio jako ciągi znaków. W praktyce ze względów bezpieczeństwa częściej wykorzystuje się wersję zawierającą tak zwane zastępniki (ang. placeholders ), czyli umowne znaki, które zostają zastąpione przez wartości podane w tupli lub liście. Prześledźmy przykłady.
Przykład 8
Dodanie jednego rekordu do tabeli z wykorzystaniem zapytania z zastępnikami:
Linia 1. cur kropka execute otwórz nawias okrągły cudzysłów INSERT INTO uczniowie VALUES otwórz nawias okrągły znak zapytania przecinek znak zapytania przecinek znak zapytania przecinek znak zapytania zamknij nawias okrągły cudzysłów przecinek otwórz nawias okrągły apostrof 123 prawy ukośnik 2011 apostrof przecinek apostrof Wojciech apostrof przecinek apostrof Banasik apostrof przecinek apostrof IV E apostrof zamknij nawias okrągły zamknij nawias okrągły.
Dodanie wielu rekordów do tabeli w pętli z wykorzystaniem zapytania z zastępnikami:
Linia 1. for rekord in dane dwukropek.
Linia 2. cur kropka execute otwórz nawias okrągły cudzysłów INSERT INTO uczniowie VALUES otwórz nawias okrągły znak zapytania przecinek znak zapytania przecinek znak zapytania przecinek znak zapytania zamknij nawias okrągły cudzysłów przecinek rekord zamknij nawias okrągły.
for rekord in dane:
cur.execute("INSERT INTO uczniowie VALUES (?, ?, ?, ?)", rekord)
W naszym przypadku, kiedy chcemy dodać do tabel wiele rekordów na raz, skorzystamy z metody executemany(), która wymaga wspomnianych zastępników w zapytaniu SQL oraz listy (lub tupli) zawierającej wartości rekordów:
Przykład 10
Linia 1. dane znak równości otwórz nawias kwadratowy.
Linia 2. otwórz nawias kwadratowy apostrof 123 prawy ukośnik 2011 apostrof przecinek apostrof Wojciech apostrof przecinek apostrof Banasik apostrof przecinek apostrof IV E apostrof zamknij nawias kwadratowy przecinek.
Linia 3. otwórz nawias kwadratowy apostrof 124 prawy ukośnik 2011 apostrof przecinek apostrof Monika apostrof przecinek apostrof Baranowska apostrof przecinek apostrof IV E apostrof zamknij nawias kwadratowy przecinek.
Linia 4. zamknij nawias kwadratowy.
Linia 5. cur kropka executemany otwórz nawias okrągły cudzysłów INSERT INTO uczniowie VALUES otwórz nawias okrągły znak zapytania przecinek znak zapytania przecinek znak zapytania przecinek znak zapytania zamknij nawias okrągły cudzysłów przecinek dane zamknij nawias okrągły.
Omówioną metodę wykorzystamy w naszym skrypcie. Do funkcji dodaj_dane() dopisz podany kod. Ze względu na czytelność wyników działania skryptu, w funkcji dodaj_dane() wstaw znaki komentarza przed pętlą for i przed instrukcją wypisującą odczytane rekordy.
Linia 1. zastepniki znak równości apostrof przecinek apostrof kropka join otwórz nawias okrągły otwórz nawias kwadratowy apostrof znak zapytania apostrof zamknij nawias kwadratowy asterysk len otwórz nawias okrągły dane otwórz nawias kwadratowy 0 zamknij nawias kwadratowy zamknij nawias okrągły zamknij nawias okrągły.
Linia 2. zapytanie znak równości apostrof INSERT INTO apostrof plus tabela plus apostrof VALUES otwórz nawias okrągły apostrof plus zastepniki plus apostrof zamknij nawias okrągły apostrof.
Linia 3. cur kropka executemany otwórz nawias okrągły zapytanie przecinek dane zamknij nawias okrągły.
Linia 4. return cur kropka rowcount.
Linia 1. def dodaj podkreślnik dane otwórz nawias okrągły cur przecinek tabela przecinek sep zamknij nawias okrągły dwukropek.
Linia 2. plik podkreślnik csv znak równości tabela plus apostrof kropka csv apostrof.
Linia 3. if not os kropka path kropka isfile otwórz nawias okrągły plik podkreślnik csv zamknij nawias okrągły dwukropek.
Linia 4. print otwórz nawias okrągły f cudzysłów Brak pliku otwórz nawias klamrowy plik podkreślnik csv zamknij nawias klamrowy na dysku wykrzyknik cudzysłów zamknij nawias okrągły.
Linia 5. return False.
Linia 6. dane znak równości otwórz nawias kwadratowy zamknij nawias kwadratowy kratka lista na listy rekordów.
Linia 7. with open otwórz nawias okrągły plik podkreślnik csv przecinek newline znak równości apostrof apostrof przecinek encoding znak równości apostrof utf minus 8 apostrof zamknij nawias okrągły as plik dwukropek.
Linia 8. for wiersz in csv kropka reader otwórz nawias okrągły plik przecinek delimiter znak równości sep zamknij nawias okrągły dwukropek.
Linia 9. kratka wiersz znak równości otwórz nawias kwadratowy x kropka strip otwórz nawias okrągły zamknij nawias okrągły for x in wiersz zamknij nawias kwadratowy.
Linia 10. dane kropka append otwórz nawias okrągły wiersz zamknij nawias okrągły.
Linia 11. kratka for rekord in dane dwukropek.
Linia 12. kratka print otwórz nawias okrągły dane zamknij nawias okrągły.
Linia 14. zastepniki znak równości apostrof przecinek apostrof kropka join otwórz nawias okrągły otwórz nawias kwadratowy apostrof znak zapytania apostrof zamknij nawias kwadratowy asterysk len otwórz nawias okrągły dane otwórz nawias kwadratowy 0 zamknij nawias kwadratowy zamknij nawias okrągły zamknij nawias okrągły.
Linia 15. zapytanie znak równości apostrof INSERT INTO apostrof plus tabela plus apostrof VALUES otwórz nawias okrągły apostrof plus zastepniki plus apostrof zamknij nawias okrągły apostrof.
Linia 16. cur kropka executemany otwórz nawias okrągły zapytanie przecinek dane zamknij nawias okrągły.
Linia 17. return cur kropka rowcount.
def dodaj_dane(cur, tabela, sep):
plik_csv = tabela + '.csv'
if not os.path.isfile(plik_csv):
print(f"Brak pliku {plik_csv} na dysku!")
return False
dane = [] # lista na listy rekordów
with open(plik_csv, newline='', encoding='utf-8') as plik:
for wiersz in csv.reader(plik, delimiter=sep):
# wiersz = [x.strip() for x in wiersz]
dane.append(wiersz)
# for rekord in dane:
# print(dane)
zastepniki = ','.join(['?'] * len(dane[0]))
zapytanie = 'INSERT INTO ' + tabela + ' VALUES(' + zastepniki + ')'
cur.executemany(zapytanie, dane)
return cur.rowcount
Instrukcja zastepniki = ','.join(['?'] * len(dane[0])) tworzy ciąg znakowy zastępników. Wyrażenie ['?'] * len(dane[0]) zwraca listę zawierającą tyle znaków zapytania, ile wartości ma pierwszy dodawany rekord. Metoda join() zwraca elementy listy połączone przecinkiem, np. '?,?,?,?', jeżeli dodawany rekord zawiera 4 pola (wartości).
Ostatnia instrukcja return cur.rowcount zwraca liczbę zmodyfikowanych rekordów, co możemy wykorzystać jako potwierdzenie, że operacja się udała.
Ćwiczenie 4
W funkcji głównej zmienimy i wstawimy wywołania funkcji dodaj_dane():
Linia 1. cur kropka execute otwórz nawias okrągły apostrof PRAGMA FOREIGN podkreślnik KEYS znak równości ON apostrof zamknij nawias okrągły.
Linia 2. print otwórz nawias okrągły dodaj podkreślnik dane otwórz nawias okrągły cur przecinek apostrof uczniowie apostrof przecinek apostrof lewy ukośnik t apostrof zamknij nawias okrągły zamknij nawias okrągły kratka dodawanie danych.
Linia 3. print otwórz nawias okrągły dodaj podkreślnik dane otwórz nawias okrągły cur przecinek apostrof przedmioty apostrof przecinek apostrof przecinek apostrof zamknij nawias okrągły zamknij nawias okrągły kratka dodawanie danych.
Linia 4. print otwórz nawias okrągły dodaj podkreślnik dane otwórz nawias okrągły cur przecinek apostrof oceny apostrof przecinek apostrof lewy ukośnik t apostrof zamknij nawias okrągły zamknij nawias okrągły kratka dodawanie danych.
cur.execute('PRAGMA FOREIGN_KEYS = ON')
print(dodaj_dane(cur, 'uczniowie', '\t')) # dodawanie danych
print(dodaj_dane(cur, 'przedmioty', ',')) # dodawanie danych
print(dodaj_dane(cur, 'oceny', '\t')) # dodawanie danych
Kod funkcji głównej po zmianach:
Linia 1. def main otwórz nawias okrągły args zamknij nawias okrągły dwukropek.
Linia 2. baza znak równości apostrof uczniowie kropka db apostrof.
Linia 3. con znak równości sqlite3 kropka connect otwórz nawias okrągły baza zamknij nawias okrągły kratka połączenie z bazą.
Linia 4. cur znak równości con kropka cursor otwórz nawias okrągły zamknij nawias okrągły kratka utworzenie obiektu kursora.
Linia 6. cur kropka execute otwórz nawias okrągły apostrof PRAGMA FOREIGN podkreślnik KEYS znak równości ON apostrof zamknij nawias okrągły.
Linia 7. print otwórz nawias okrągły dodaj podkreślnik dane otwórz nawias okrągły cur przecinek apostrof uczniowie apostrof przecinek apostrof lewy ukośnik t apostrof zamknij nawias okrągły zamknij nawias okrągły kratka dodawanie danych.
Linia 8. print otwórz nawias okrągły dodaj podkreślnik dane otwórz nawias okrągły cur przecinek apostrof przedmioty apostrof przecinek apostrof przecinek apostrof zamknij nawias okrągły zamknij nawias okrągły kratka dodawanie danych.
Linia 9. print otwórz nawias okrągły dodaj podkreślnik dane otwórz nawias okrągły cur przecinek apostrof oceny apostrof przecinek apostrof lewy ukośnik t apostrof zamknij nawias okrągły zamknij nawias okrągły kratka dodawanie danych.
Linia 11. con kropka commit otwórz nawias okrągły zamknij nawias okrągły kratka zatwierdzenie zmian w bazie.
Linia 12. con kropka close otwórz nawias okrągły zamknij nawias okrągły kratka zamknięcie połączenia z bazą.
Linia 13. return 0.
def main(args):
baza = 'uczniowie.db'
con = sqlite3.connect(baza) # połączenie z bazą
cur = con.cursor() # utworzenie obiektu kursora
cur.execute('PRAGMA FOREIGN_KEYS = ON')
print(dodaj_dane(cur, 'uczniowie', '\t')) # dodawanie danych
print(dodaj_dane(cur, 'przedmioty', ',')) # dodawanie danych
print(dodaj_dane(cur, 'oceny', '\t')) # dodawanie danych
con.commit() # zatwierdzenie zmian w bazie
con.close() # zamknięcie połączenia z bazą
return 0
W przedstawionym kodzie warto zauważyć, że aby poprawnie dodać dane do tabel, musimy pamiętać o podawaniu odpowiedniego separatora danych oraz o kolejności dodawania danych – przy założeniu, że baza sprawdza zdefiniowane ograniczenia.
W bazach SQLite3 ograniczenia FOREIGN KEY są domyślnie wyłączone, włączamy je więc, wykonując zapytanie PRAGMA FOREIGN_KEYS = ON. Tabela oceny zawiera klucze obce, czyli pola id_ucznia i id_przedm, w których wartości muszą odpowiadać wartościom z tabel i pól powiązanych relacjami, a więc dane powinny zostać dodane najpierw do tabel uczniowie i przedmioty.
Ćwiczenie 5
Uruchom skrypt uczniowie_dane.py.
W przypadku błędów przeczytaj uważnie komunikaty i postaraj się je poprawić. Jeżeli tylko część danych zostanie dodana poprawnie, ponowne uruchomienie skryptu może generować błędy. Usuń wtedy bazę, czyli plik uczniowie.db, następnie uruchom skrypt uczniowie.py, tworzący bazę i tabele, a dopiero później skrypt uczniowie_dane.py. Czynności te możesz powtarzać.
Poprawny wynik działania skryptu,wypisujący liczbę dodanych do tabel rekordów:
Linia 1. 762.
Linia 2. 27.
Linia 3. 13195.
762
27
13195
Słownik
format CSV
format CSV
standard zapisywania informacji z bazy danych w pliku tekstowym, w którym pola każdego rekordu oddzielone separatorem (np. przecinkiem) zapisywane są w kolejnych wierszach
kursor
kursor
(ang. cursor) obiekt pozwalający komunikować się z bazą danych, czyli wykonywać zapytania SQL, a także umożliwiający pobieranie kolejnych rekordów, zwróconych przez zapytania
tabela słownikowa
tabela słownikowa
tabela zawierająca listę wartości, które dopuszczalne są w polu innej tabeli powiązanej relacją