Dieses Tutorial führt sie Schritt für Schritt in die Konsolen-basierte Verwendung und Abfrage einer SQLite Datenbank ein. Grundlegende Kenntnisse über relationale Datenbanken und SQL Abfragen werden vorausgesetzt.
Zum Nachvollziehen der folgenden Schritte benötigen sie einige Dateien:
id
: eindeutige Identifikationsnummer der Firmaname
: Name der Firmacountry
: Land der Firmaid
: eindeutige Identifikationsnummer des Reviewscompany_id
: Identifikationsnummer der Firma (Verweis
auf die id in der Tabelle company), die diese Schokolade hergestellt
hatbar_name
: Name des Schokoriegelsyear
: Jahr des Reviewscoca_pct
: Kakaoanteil zwischen 0 und 1rating
: Bewertung zwischen 1 und 5bean_type
: Kakaobohnen-Sorte (fehlt bei vielen
Einträgen)bean_origin
: Kakaobohnen-Herkunft (fehlt bei vielen
Einträgen)sudo apt install sqlite3
https://sqlite.org/download.html
Für Windows am besten sqlite-tools-win32-x86-xxx.zip
.
Entpacken in ein beliebiges Verzeichnis. Dieses Verzeichnis dann zur
Windows-Umgebungsvariable „Path
“ hinzufügen (Wie
geht das?)
sqlite3 --version
Sollte mindestens 3.30
sein.
Nun starten wir SQLite Konsole mit einer Datenbank. Dafür einfach als Argument den Dateinamen (z.B. schokolade.db) der Datenbank übergeben:
sqlite3 schokolade.db
Wenn die Datenbankdatei bereits existiert, wird sie geöffnet. Ansonsten wird eine neue Datenbank in dieser Datei angelegt.
Nun sind wir in der SQLite Konsole, die Ausgabe sollte wie folgt aussehen:
SQLite version 3.37.2 2022-01-06 13:25:41
Enter ".help" for usage hints.
sqlite>
Bei diesem Prompt kann man nun zwei Arten von Kommandos absetzen:
Eine komplette Liste der Dot-Kommandos erhält man mit dem Kommando
“.help
” (hier nur eine Auswahl dargestellt):
sqlite> .help
.backup ?DB? FILE Backup DB (default "main") to FILE
.cd DIRECTORY Change the working directory to DIRECTORY
.changes on|off Show number of rows changed by SQL
.clone NEWDB Clone data into NEWDB from the existing database
.dump ?OBJECTS? Render database content as SQL
.echo on|off Turn command echo on or off
.excel Display the output of next command in spreadsheet
.exit ?CODE? Exit this program with return-code CODE
.headers on|off Turn display of headers on or off
.help ?-all? ?PATTERN? Show help text for PATTERN
.import FILE TABLE Import data from FILE into TABLE
.limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT
.mode MODE ?TABLE? Set output mode
.nullvalue STRING Use STRING in place of NULL values
.once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE
.open ?OPTIONS? ?FILE? Close existing database and reopen FILE
.quit Exit this program
.read FILE Read input from FILE
.schema ?PATTERN? Show the CREATE statements matching PATTERN
.separator COL ?ROW? Change the column and row separators
.shell CMD ARGS... Run CMD ARGS... in a system shell
.show Show the current values for various settings
.tables ?TABLE? List names of tables matching LIKE pattern TABLE
.width NUM1 NUM2 ... Set minimum column widths for columnar output
Detaillierte Erklärungen aller Kommandos gibt es unter https://sqlite.org/cli.html
Das Kommando “.tables
” zeigt uns, dass die Datenbank
noch leer ist. Daher erzeugen wir mal die Tabellen
“company
” und “reviews
”.
Dafür gibt es zwei Möglichkeiten: entweder die Kommandos in die
Konsole schreiben, oder die Kommandos in eine Datei (z.B. create_tables.sql) speichern und diese
mit “.read
” ausführen:
sqlite> .read create_tables.sql
sqlite> .tables
company review
Die Tabellen sind nun angelegt aber leer. Man kann nun die Tabellen
zeilenweise füllen mit dem SQL Kommando “insert into
”, wir
wollen aber lieber die Tabellen aus den CSV-Dateien füttern. Dafür gibt
es das Kommando “.import
”. Lassen wir uns mal die Hilfe zum
Import anzeigen:
sqlite> .help import
.import FILE TABLE Import data from FILE into TABLE
Options:
--ascii Use \037 and \036 as column and row separators
--csv Use , and \n as column and row separators
--skip N Skip the first N rows of input
-v "Verbose" - increase auxiliary output
Notes:
* If TABLE does not exist, it is created. The first row of input
determines the column names.
* If neither --csv or --ascii are used, the input mode is derived
from the ".mode" output mode
* If FILE begins with "|" then it is a command that generates the
input text.
Wir werden also die Option “--csv
” verwenden, und die
erste Zeile (Spaltennamen) mittels “--skip 1
” übergehen.
Wenn keine Fehlermeldung kommt, kann man davon ausgehen, dass alles
funktioniert hat. Wir gucken trotzdem wie viele Zeilen in company
eingetragen wurden:
sqlite> .import --csv --skip 1 company.csv company
sqlite> select count(*) from company;
418
Das gleiche noch mit den Reviews, und voila die Datenbank ist gefüllt und bereit für unsere Abfragen:
sqlite> .import --csv --skip 1 review.csv review
sqlite> select count(*) from review;
1795
Warum haben wir erst “company
” und dann erst
“review
” gefüllt?
Da die Einträge in Spalte “company_id
” in Tabelle
“review
” auf die id
Daten in
“company
” verweisen.
Man kann nun Abfragen in SQL formulieren, die Ergebnisse werden entsprechend ausgegeben, z.B. Jahreszahl und Bewertung aller Reviews für Schokoladen aus Vietnam:
sqlite> select year, rating from review where bean_origin = "Vietnam";
2014|2.75
2017|3.5
2016|3.5
2016|3.25
2010|3.25
[... einige ausgeblendete Zeilen...]
2016|3.0
2016|4.0
2015|3.25
2015|3.25
2012|3.5
Wir sehen die Ausgabe ist ohne Spaltenüberschrift und das verwendete Trennzeichen ist die Pipe. Das kann man mit den Kommandos .headers und .separator ändern, z.B. mit Tabulator als Trennzeichen:
sqlite> .headers on
sqlite> .separator "\t"
sqlite> select year, rating from review where bean_origin = 'Vietnam';
year rating
2014 2.75
2017 3.5
2016 3.5
2016 3.25
2010 3.25
[... einige ausgeblendete Zeilen...]
2016 3.0
2016 4.0
2015 3.25
2015 3.25
2012 3.5
Das Format der Ausgabe von Abfrageergebnissen kann man unter anderem
über das Kommando “.mode
” voreinstellen. Der Standardmodus
ist “list
”, man kann aber z.B. auch CSV oder als Tabelle
ausgeben lassen:
sqlite> .help mode
.mode MODE ?TABLE? Set output mode
MODE is one of:
ascii Columns/rows delimited by 0x1F and 0x1E
box Tables using unicode box-drawing characters
csv Comma-separated values
column Output in columns. (See .width)
html HTML <table> code
insert SQL insert statements for TABLE
json Results in a JSON array
line One value per line
list Values delimited by "|"
markdown Markdown table format
quote Escape answers as for SQL
table ASCII-art table
tabs Tab-separated values
tcl TCL list elements
Wollen wir beispielsweise ein Abfrageergebnis als CSV-Datei
speichern, so stellen wir den Ausgabemodus auf “csv
” und
verwenden das Kommando “.once
” um die Ausgabe in eine Datei
zu leiten:
sqlite> .once ergebnis.csv
sqlite> select year, rating from review where bean_origin = 'Vietnam';
Um SQLite in einen Verarbeitungspipeline zu verwenden, kann man SQLite auch ohne interaktive Konsole verwenden:
> sqlite3 -help
Usage: sqlite3 [OPTIONS] FILENAME [SQL]
FILENAME is the name of an SQLite database. A new database is created
if the file does not previously exist.
OPTIONS include:
-A ARGS... run ".archive ARGS" and exit
-append append the database to the end of the file
-ascii set output mode to 'ascii'
-bail stop after hitting an error
-batch force batch I/O
-box set output mode to 'box'
-column set output mode to 'column'
-cmd COMMAND run "COMMAND" before reading stdin
-csv set output mode to 'csv'
-deserialize open the database using sqlite3_deserialize()
-echo print commands before execution
-init FILENAME read/process named file
-[no]header turn headers on or off
-help show this message
-html set output mode to HTML
-interactive force interactive I/O
-json set output mode to 'json'
-line set output mode to 'line'
-list set output mode to 'list'
-lookaside SIZE N use N entries of SZ bytes for lookaside memory
-markdown set output mode to 'markdown'
-maxsize N maximum size for a --deserialize database
-memtrace trace all memory allocations and deallocations
-mmap N default mmap size set to N
-newline SEP set output row separator. Default: '\n'
-nofollow refuse to open symbolic links to database files
-nonce STRING set the safe-mode escape nonce
-nullvalue TEXT set text string for NULL values. Default ''
-pagecache SIZE N use N slots of SZ bytes each for page cache memory
-quote set output mode to 'quote'
-readonly open the database read-only
-safe enable safe-mode
-separator SEP set output column separator. Default: '|'
-stats print memory stats before each finalize
-table set output mode to 'table'
-tabs set output mode to 'tabs'
-version show SQLite version
-vfs NAME use NAME as the default VFS
-zip open the file as a ZIP Archive
(Je nach verwendeter SQLite-Version können bei Ihnen weniger oder mehr als die hier gelisteten Optionen möglich sein.)
Nun wollen wir das Ergebnis unserer Vietnam-Abfrage direkt in der BASH ausgeben lassen (ohne interaktive SQLite-Konsole):
$ sqlite3 -csv -readonly schokolade.db \
"select year, rating from review where bean_origin = 'Vietnam'"
Beachten: das “\
” am Zeilenende führt zum
Ignorieren des Zeilenumbruchs, sodass der Befehl in der nächsten Zeile
fortgeführt werden kann. (Aber nur, wenn nach dem “\
” kein
weiteres Leerzeichen etc. sondern direkt der Zeilenumbruch folgt!)
Nun wollen wir ein CSV-File in eine temporäre SQLite-Datenbank füttern und anschließend eine Abfrage machen, deren Ergebnis als CSV ausgegeben wird.
Gucken wir zunächst in die CSV-Datei review.csv, die ersten paar Zeilen sehen wie folgt aus:
$ head -n 10 review.csv
id,company_id,bar_name,year,cocoa_pct,rating,bean_type,bean_origin
436,1,"Agua Grande",2016,0.63,3.75,,"Sao Tome"
437,1,Kpime,2015,0.7,2.75,,Togo
438,1,Atsane,2015,0.7,3.0,,Togo
439,1,Akata,2015,0.7,3.5,,Togo
440,1,Quilla,2015,0.7,3.5,,Peru
441,1,Carenero,2014,0.7,2.75,Criollo,Venezuela
442,1,Cuba,2014,0.7,3.5,,Cuba
443,1,"Sur del Lago",2014,0.7,3.5,Criollo,Venezuela
444,1,"Puerto Cabello",2014,0.7,3.75,Criollo,Venezuela
Jetzt pipen wir die komplette CSV-Datei in eine temporäre SQLite-Datenbank, führen die SQL Abfrage aus und gucken uns die ersten 10 Zeilen des Ergebnisses an:
$ cat review.csv | sqlite3 :memory: ".mode csv" ".import /dev/stdin review" \
"select year, rating from review where bean_origin = 'Vietnam'" | head -n 10
2014,2.75
2017,3.5
2016,3.5
2016,3.25
2010,3.25
2015,3.5
2015,2.75
2016,2.75
2016,3.0
2016,3.5
Um zu erklären, was bei obigen Aufruf von sqlite3 passiert, wird dieser im Folgenden nochmal in seine Teile zerlegt und diskutiert:
sqlite3 \
:memory: \
".mode csv" \
".import /dev/stdin review" \
"select year, rating from review where bean_origin = 'Vietnam'"
:memory:
ist ein spezieller “Dateiname” in SQLite, der
andeutet, dass wir die Datenbank nicht in eine Datei auf den Datenträger
speichern wollen, sondern mit einer temporären In-Memory-Datenbank
arbeiten wollen, die so lange im Arbeitsspeicher existiert, wie das
sqlite3 Kommando läuft.".mode csv"
müssen wir vor dem Import-Kommando
verwenden, um CSV importieren zu können, und auch um CSV ausgeben zu
lassen. Diese Notwendigkeit ergibt sich aus der Dokumentation: „Note
that it is important to set the “mode” to “csv” before running the
“.import” command. This is necessary to prevent the command-line shell
from trying to interpret the input file text as some other
format.“".import /dev/stdin review"
veranlasst SQLite, von
/dev/stdin zu lesen; das ist die Standardeingabe, also das was via cat
review.csv an sqlite3 geliefert wird. Das CSV soll in die Tabelle review
importiert werden."select ..."
ist die SQL-Abfrage, die wir ausführen
wollen.Um beispielsweise die Anzahl der Zeilen im Abfrageergebnis zu
ermitteln, können wir den Output von sqlite3 zum Zeilenzählen an
wc
pipen, und sehen es gibt 38 Reviews von vietnamesischen
Schokoladen:
$ cat review.csv | sqlite3 :memory: ".mode csv" ".import /dev/stdin review" \
"select * from review where bean_origin = 'Vietnam'" | wc -l
38
Download: PDF Version dieses Tutorials. Erstellt am 25.07.2024.