diff --git a/README.md b/README.md index a6d7c7c..51abc93 100644 --- a/README.md +++ b/README.md @@ -70,11 +70,30 @@ column names in the following tables. We'll use `setup.sql` later. * A reference to an `id` in table `album` (the album the track is on). This should be a _foreign key_. +```sql +CREATE TABLE track( + id INTEGER PRIMARY KEY AUTOINCREMENT, + title VARCHAR(128) NOT NULL, + album_id INTEGER NOT NULL, + FOREIGN KEY(album_id) REFERENCES album(id) +); +``` + * Create a table called `artist_album` to connect artists to albums. (Note that an artist might have several albums and an album might be created by multiple artists.) * Use foreign keys for this, as well. + ```sql + CREATE TABLE artist_album( + id INTEGER PRIMARY KEY AUTOINCREMENT, + artist_id INTEGER NOT NULL, + album_id INTEGER NOT NULL, + FOREIGN KEY(artist_id) REFERENCES artist(id), + FOREIGN KEY(album_id) REFERENCES album(id) + ); + ``` + * Run the queries in the file `setup.sql`. This will populate the tables. * Fix any errors at this point by making sure your tables are correct. * `DROP TABLE` can be used to delete a table so you can recreate it with @@ -82,24 +101,83 @@ column names in the following tables. We'll use `setup.sql` later. * Write SQL `SELECT` queries that: * Show all albums. + ```sql + SELECT * FROM album; + ``` * Show all albums made between 1975 and 1990. + ```sql + SELECT * FROM album WHERE release_year BETWEEN 1975 AND 1990; + ``` * Show all albums whose names start with `Super D`. + ```sql + SELECT * FROM album WHERE title LIKE 'Super D%'; + ``` * Show all albums that have no release year. + ```sql + SELECT * FROM album WHERE release_year IS NULL; + ``` + +--- + +Great resources: +* [sqlite-select](http://www.sqlitetutorial.net/sqlite-select/) +* [sqlite-where](http://www.sqlitetutorial.net/sqlite-where/) +* [where-isnull](https://www.dofactory.com/sql/where-isnull) +* [sqlite-avg](http://www.sqlitetutorial.net/sqlite-avg/) +* [formatting sqlite shell output](https://dba.stackexchange.com/a/40672) + +--- * Write SQL `SELECT` queries that: * Show all track titles from `Super Funky Album`. + ```sql + SELECT track.title + FROM track + JOIN album ON album.id = track.album_id + WHERE album.title IS 'Super Funky Album'; + ``` * Same query as above, but rename the column from `title` to `Track_Title` in the output. - + ```sql + SELECT track.title AS Track_Title + FROM track + JOIN album ON album.id = track.album_id + WHERE album.title IS 'Super Funky Album'; + ``` * Select all album titles by `Han Solo`. - + ```sql + SELECT artist.name AS Artist, album.title AS Album_Title + FROM album + JOIN artist_album ON artist_album.album_id = album.id + JOIN artist ON artist.id = artist_album.artist_id + WHERE artist.name IS 'Han Solo'; + ``` * Select the average year all albums were released. + ```sql + SELECT avg(release_year) FROM album; + ``` * Select the average year all albums by `Leia and the Ewoks` were released. + ```sql + SELECT AVG(release_year) + FROM album + JOIN artist_album ON artist_album.album_id = album.id + JOIN artist ON artist.id = artist_album.artist_id + WHERE artist.name IS 'Leia and the Ewoks'; + ``` * Select the number of artists. + ```sql + SELECT COUNT(*) AS Number_of_Artists FROM artist; + ``` * Select the number of tracks on `Super Dubstep Album`. + ```sql + SELECT COUNT(*) AS Number_of_Tracks + FROM track + JOIN album ON album.id = track.album_id + WHERE album.title IS 'Super Dubstep Album'; + ``` ### Exercises, Day 2 @@ -107,12 +185,28 @@ Create a database for taking notes. * What are the columns that a note table needs? +|Columns |Relation | +|:---: |:---: | +|id |Primary | +|title | | +|note_text | | +|date_created | | +|author_id |Foreign | + * If you have a timestamp field, how do you auto-populate it with the date? +Per this [StackOverflow answer](https://stackoverflow.com/a/14462319), use `CURRENT_TIMESTAMP` +as the default value. + * A note should have a foreign key pointing to an author in an author table. * What columns are needed for the author table? +|Columns |Relation | +|:---: |:---: | +|id |Primary | +|author_name | | + Write queries that: * Insert authors to the author table. @@ -129,9 +223,13 @@ Write queries that: > Note that SQLite doesn't enforce foreign key constrains by default. You have > to enable them by running `PRAGMA foreign_keys = ON;` before your queries. - * What happens when you try to delete an author with an existing note? - * How can you prevent this? + * What happens when you try to delete an author with an existing note?
+ `FOREIGN KEY constraint failed`
+ This happens because we are trying to authors, but will end up leaving notes with foreign keys pointing to nowhere if we do so, so the deletion is stopped. + * How can you prevent this? + We can set `ON DELETE CASCADE`, which will delete all related rows with a foreign key matching the author being deleted. + Submit a file `notes.sql` with the queries that build (`CREATE TABLE`/`INSERT`) and query the database as noted above. diff --git a/music.db b/music.db new file mode 100644 index 0000000..8a36140 Binary files /dev/null and b/music.db differ diff --git a/notes.db b/notes.db new file mode 100644 index 0000000..669d760 Binary files /dev/null and b/notes.db differ diff --git a/notes.sql b/notes.sql new file mode 100644 index 0000000..282494a --- /dev/null +++ b/notes.sql @@ -0,0 +1,66 @@ +CREATE TABLE note( + id INTEGER PRIMARY KEY AUTOINCREMENT, + title VARCHAR(128) DEFAULT 'New Note', + note_text TEXT, + author_id INTEGER NOT NULL, + date_created DATETIME DEFAULT CURRENT_DATE, + FOREIGN KEY(author_id) REFERENCES author(id) ON DELETE CASCADE +); + +CREATE TABLE author( + id INTEGER PRIMARY KEY AUTOINCREMENT, + author_name VARCHAR(64) NOT NULL +); + +INSERT INTO author (id, author_name) VALUES (1, "Alfa"); +INSERT INTO author (id, author_name) VALUES (2, "Bravo"); +INSERT INTO author (id, author_name) VALUES (3, "Charlie"); + +INSERT INTO note (id, title, note_text, author_id) VALUES ( + 1, + 'My friend Omega', + 'My friend, Omega, is the last word when it comes to friendship', + 1 +); + +INSERT INTO note (id, title, note_text, author_id) VALUES ( + 2, + 'Lorem Ipsum', + 'Cras aliquam, diam ut pretium ultrices, quam lectus pretium nulla, at molestie lacus nisl sed eros. Aliquam vitae lacus quis quam eleifend mattis. Mauris tempor pulvinar facilisis.', + 1 +); + +INSERT INTO note (id, title, note_text, author_id) VALUES ( + 3, + 'My favorite television channel', + 'My favorite television channel on cable is Lifetime. It is the best.', + 2 +); + +INSERT INTO note (id, title, note_text, author_id) VALUES ( + 4, + 'Dissertation on Chocolate Factories', + 'Access to the means of chocolate production should not be reserved for the golden-tickted elite, but for the hungry and impoverished masses!', + 3 +); + +.headers ON +.mode column + +SELECT * + FROM note + JOIN author ON author.id = note.author_id; + +SELECT * + FROM note + WHERE note.id = 4; + +SELECT author.author_name, COUNT(note.title) AS Num_of_Notes + FROM note + JOIN author ON author.id = note.author_id + GROUP BY author.author_name; + +PRAGMA foreign_keys = ON; + +DELETE + FROM author; \ No newline at end of file