Music App Database
Let’s imagine we’re building a new music app, where listeners can play songs and keep track of which songs they played and when. Five beta testers have been using a prototype of the app; their data has been saved to a few CSV files, and now we want to design and use a database that can power the app.
Remix this Replit to follow along:
Looking Around
After you remix the Replit, click around in the files and see if you can determine what each file does and why it’s there. Make sure the sidebar on the left is open, as shown in the picture to the right.
main.sql- This is the file that is run when we hit the Run button in Replit.
- Notice that we
.readthe other two sql files in the Setup Section in this File. - We will be working in this file to practice our SQL skills.
create_tables.sql- This file creates the tables that our CSV data will be read into.
- Take some time to read through each of the
create tablestatements. Pay attention to the data types and column names. - Something new here! Some tables, such as the
albumstable, contain something called a foreign key. See the section below on what this is.
import_data.sql- This file, which is run after the
create_tables.sqlfile, loads the data from the CSV files into the SQLite database. - Discuss: Why do you think this file has to be run after the
create_tables.sqlfile?
datadirectory, including the files:albums.csvartists.csvlisteners.csvplays.csvsongs.csv- “CSV” stands for “comma-separated values.” Each line in a CSV document represents one record in the table. The different fields are separated by commas, hence the name.
- These files contain the data that we will load into the SQLite database. Once we do that, we can run queries against the data.
- Notice that the CSV header row (the first row) contains the same column names as the columns we create for each table in the
create_tables.sqlfile.

Foreign Keys
A foreign key constraint is a rule that helps keep our data accurate and consistent. It ensures that a column in one table only contains values that exist in a specific column of another table.
For example, the
songs.album_id column has a foreign key constraint that requires every value in that column to also exist in the albums.album_id column.This means:
- If we try to insert a song with an
album_idthat isn’t in thealbumstable, we’ll get an error.
- If we try to delete an album from the
albumstable while there are songs referencing thatalbum_id, we’ll also get an error.
This constraint prevents data that is incomplete or doesn’t make sense and keeps relationships between tables valid.
erDiagram ALBUM ||--|{ SONG : has ALBUM { integer album_id PK text title integer artist_id FK date release_date } SONG { integer song_id PK text title integer album_id FK }
Code-Along | Music App Database
The Setup Section in main.sql
We don’t need to change any code here. Let’s look at what each line does.
The commands here are called “dot commands.” They are different from queries. Instead of interacting directly with data in a table, dot commands do things like run other SQL files, print text to the output console, or change how printed text is formatted.
Code | Purpose |
.read create_tables.sql | Reads the SQL queries in the create_tables.sql file and runs them. |
.read import_data.sql | Reads the SQL queries in the import_data.sql file and runs them. |
.mode qbox | Prints the output of all queries in a table-like format in the Console, making it easier to read. |
Code-along 0
It looks like a line of code is missing from
import_data.sql! Let’s take a look at the code in that file:-- Import data from CSV .mode csv .import --skip 1 data/artists.csv artists .import --skip 1 data/albums.csv albums .import --skip 1 data/songs.csv songs .import --skip 1 data/listeners.csv listeners .import --skip 1 data/plays.csv plays
It looks like we have:
- A comment describing what these commands do. (
-- Import data from CSV)
.mode csv, which sets the import/export mode to CSV
.import --skip 1 data/artists.csv artists(and a few other lines like this one)- Isn’t everything after
.importa comment? It sure looks like one, but the syntax for dot commands is different than queries! Even though the Replit code editor colors this portion of the line as if it’s a comment, it is actually a list of arguments that specifies: - To skip the first row of the CSV during import, since that’s the header row.
- To import the data from
data/artists.csv - To load the imported data into the table
artists - Given these examples, can you write a line at the end of the file to import the data from
data/plays.csvinto theplaystable?
Once you’re done:
- Run the Replit to check that you don’t have any errors.
- Delete the
.printlines under Code-along 0 when you’re done. (Note:.printis a great way to print any information you want to print in the console!)
Â
For a summary of this lesson, check out the 4. Lab: Music App Database One-Pager!
Â
