Skip to content

Commit

Permalink
Merge pull request #1 from dtauer/main
Browse files Browse the repository at this point in the history
corrected spelling/grammar
  • Loading branch information
btholt authored Aug 12, 2024
2 parents 8c166e8 + 722ca2c commit ca799f2
Show file tree
Hide file tree
Showing 12 changed files with 45 additions and 44 deletions.
18 changes: 9 additions & 9 deletions lessons/01-welcome/B-what-is-sqlite.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ title: "What is SQLite?"

## A Brief History

Let's take a look back at where SQLite came from, as that can help us understand why SQLite was created in the first place and what place it has in the world of development. SQLite was written by Dr. D. Richard Hipp in 2000 while he was working on a contract for the United States Navy writing software for destroyers. He evaluated other database engines but ended designing his own implementation.
Let's take a look back at where SQLite came from, as that can help us understand why SQLite was created in the first place and what place it has in the world of development. SQLite was written by Dr. D. Richard Hipp in 2000 while he was working on a contract for the United States Navy writing software for destroyers. He evaluated other database engines but ended up designing his own implementation.

Now SQLite is [open source][timeline] ([GitHub mirror][gh]) and released to the public domain but it is not open contribution. Dr. Hipp keeps a tight control on the software and only lets a few people contribute. Notably, SQLite does not use Git but instead Fossil. [This is a nice little summary of how they differ][diff]. Fossil was created specifically by Dr. Hipp for the maintenance of SQLite (much like Git was for Linux.)
Now SQLite is [open source][timeline] ([GitHub mirror][gh]) and released to the public domain but it is not open to contributions. Dr. Hipp keeps tight control on the software and only lets a few people contribute. Notably, SQLite does not use Git but instead Fossil. [This is a nice little summary of how they differ][diff]. Fossil was created specifically by Dr. Hipp for the maintenance of SQLite (much like Git was for Linux.)

In practice you don't really need to care. The thing to take away is that Dr. Hipp and the SQLite crew take immense care of the project and are very thoughtful of maintaining an amazing project.
In practice you don't really need to care. The thing to take away is that Dr. Hipp and the SQLite crew take immense care of the project and are very thoughtful in maintaining an amazing project.

## The Most Widely Deployed and Used Database Engine

Expand All @@ -32,23 +32,23 @@ According to their website, SQLite is used in:

Many of these will continue actually hundreds of individual SQLite databases. This leads them to estimate that there are over 1,000,000,000,000 (trillion) SQLite databases!

Suffice to say, it's one of (if the not **the**) most battle-tested piece of software. It runs everywhere and incredibly reliably so.
Suffice to say, it's one of (if not **the**) most battle-tested piece of software. It runs everywhere and incredibly reliably so.

## What is SQLite not?

SQLite is not a server. It is not a standalone piece of software but instead a library designed to be attached to a running program. Importantly for you, especially if you've used something like Postgres, MySQL, MongoDB, or any other piece of database software before, you won't have a database _server_ running. SQLite will just create a database file locally on your computer. Your SDK, CLI, or whatever method of accessing your database will just be pointed at that file and that's how you'll read and write to your database.
SQLite is not a server. It is not a standalone piece of software but instead, a library designed to be attached to a running program. Importantly for you, especially if you've used something like Postgres, MySQL, MongoDB, or any other piece of database software before, you won't have a database _server_ running. SQLite will just create a database file locally on your computer. Your SDK, CLI, or whatever method of accessing your database will just be pointed at that file and that's how you'll read and write to your database.

Importantly **SQLite has no network access**. In and of itself, it doesn't handle ports, connections, etc. unlike most other database engines. SQLite was designed to work on the same computer as the app using it
Importantly **SQLite has no network access**. In and of itself, it doesn't handle ports, connections, etc. unlike most other database engines. SQLite was designed to work on the same computer as the app using it.

SQLite is single node. Whereas other databases have replication and consensus, SQLite is designed to be a node of one. You can still do backups and other things like that, but there's no concept of primary/leader and secondary/follower.
SQLite is a single node. Whereas other databases have replication and consensus, SQLite is designed to be a node of one. You can still do backups and other things like that, but there's no concept of primary/leader and secondary/follower.

SQLite is unbelievably fast. Because we don't have replication nor networks to deal with, queries take microseconds instead of milliseconds.
SQLite is unbelievably fast. Because we don't have replication or networks to deal with, queries take microseconds instead of milliseconds.

## Can I use SQLite in production?

Yes and no. No replication is a tight bottleneck and no network access means you need more tools to use SQLite as a distributed database. So, yes, you can, but you need more tools.

The startup I work at, [SQLite Cloud][cloud] is a paid service that can do this for you (with a generous free tier). [LiteFS][litefs] is an open source way to do it yourself.
The startup I work at, [SQLite Cloud][cloud] is a paid service that can do this for you (with a generous free tier). [LiteFS][litefs] is an open-source way to do it yourself.

[timeline]: https://sqlite.org/src/timeline
[gh]: https://github.com/sqlite/sqlite?tab=readme-ov-file
Expand Down
2 changes: 1 addition & 1 deletion lessons/02-running-sqlite/A-installing-sqlite.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Installing SQLite"
---

What's great is that SQLite is probably already on your device. For Windows you may have to look for it but in MacOS and Linux, you should be able to get just run `sqlite3` and it should get you into a temporary session.
What's great is that SQLite is probably already on your device. For Windows you may have to look for it but in MacOS and Linux, you should be able to run `sqlite3` and it should get you into a temporary session.

### Windows

Expand Down
8 changes: 4 additions & 4 deletions lessons/02-running-sqlite/B-getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ Use ".open FILENAME" to reopen on a persistent database.
sqlite>
```

Importantly, you'll see that we're connected to an in-memory database which means whatever we do in this session will be thrown away at the end. If you give a filename as an arguement (e.g. `sqlite3 my-data.db`) then it'll either open that file if it's exists or create it if it doesn't.
Importantly, you'll see that we're connected to an in-memory database which means whatever we do in this session will be thrown away at the end. If you give a filename as an argument (e.g. `sqlite3 my-data.db`) then it'll either open that file if it exists or create it if it doesn't.

## Dot Commands

Type `.help` (note the leading period) into your session and hit enter. You should see a long list of possible commands you can run. The dot in front signifies that it's a dot command which are special administrative commands you can pass to SQLite to do something or get some information. This will be things like export your database to CSV, report potential bugs, open a file, etc. In other words, it's anything that isn't a query. The `.help` one is super useful for you to know if you need to be reminded of what's available.
Type `.help` (note the leading period) into your session and hit enter. You should see a long list of possible commands you can run. The dot in front signifies that it's a dot command which are special administrative commands you can pass to SQLite to do something or get some information. This will be things like exporting your database to CSV, reporting potential bugs, opening a file, etc. In other words, it's anything that isn't a query. The `.help` one is super useful for you to know if you need to be reminded of what's available.

## Stopping SQLite

Easiest way is CTRL + D. `.exit` is a valid dot command that works too.
The easiest way is CTRL + D. `.exit` is a valid dot command that works too.

## Let' get it running
## Let's get it running

Let's save everything to a file. I'll be saving my database to my desktop. Do the following.

Expand Down
12 changes: 6 additions & 6 deletions lessons/03-basic-sql/A-select.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "SELECT"
---

I like to learn SQL by doing rather than some contrived explanation of how grammar is broken down and blah blah blah. I like putting fingers on keyboards and seeing what happens when we do things. Once we start to experience what SQL can do for us then we can get a bit more fine grained in terms of what is doing what and why.
I like to learn SQL by doing rather than some contrived explanation of how grammar is broken down and blah blah blah. I like putting fingers on keyboards and seeing what happens when we do things. Once we start to experience what SQL can do for us then we can get a bit more fine-grained in terms of what is doing what and why.

> Note, this is meant to be a very quick intro to general SQL. I've taught [the Complete Intro to SQL][sql] before and it's more in-depth. This class uses Postgres but 95% of the grammar applies to both. I'll highlight where there's differences.
Expand All @@ -18,7 +18,7 @@ SELECT * FROM Artist;

> Capitalization of SELECT and FROM isn't important. I usually do it out of habit because _everyone_ used to do it that way. It's not as common now and you'll see me do both.
This will return about 275 rows from the database. We asked for _every_ single artist in the Artist table and we got it! The `*` just means that we wanted every single bit of info available for every artist. We if we only wanted _some_ of the info, we could ask for that like this.
This will return about 275 rows from the database. We asked for _every_ single artist in the Artist table and we got it! The `*` just means that we wanted every single bit of info available for every artist. If we only wanted _some_ of the info, we could ask for that like this.

```sql
SELECT name from Artist;
Expand All @@ -30,21 +30,21 @@ Notice the number is gone (which was the `ArtistId`) and we just have the name f
SELECT name, ArtistId from Artist;
```

Notice the columns came back in the order you ask for them too.
Notice the columns came back in the order you asked for them too.

> If you need to get the name of columns, `.schema <TABLE_NAME>` is helpful.
## WHERE

In this case, we're querying all rows without any filtering whatsoever. Some times this is useful but normally you have an idea of some subset of rows you want. Let's say we wanted to get the ID of one of my favorite bands, The Postal Service. How would we do that?
In this case, we're querying all rows without any filtering whatsoever. Sometimes this is useful but normally you have an idea of some subset of rows you want. Let's say we wanted to get the ID of one of my favorite bands, The Postal Service. How would we do that?

```sql
SELECT ArtistID FROM Artist WHERE name = 'The Postal Service';
```

> Very important you use single quotes here. Single quotes mean a value or string literal. Double quotes in SQL refer to he name of columns and so putting double quotes would not be valid SQL.
This will just return `174` because that's all we asked for. Likewise we could do
This will just return `174` because that's all we asked for. Likewise, we could do

```sql
SELECT name FROM Artist WHERE ArtistId = 174;
Expand All @@ -62,7 +62,7 @@ Let's say you didn't know if The Postal Service was listed under "**The** Postal
SELECT ArtistID FROM Artist WHERE name LIKE '%Postal Service';
```

This will match "The Postal Service", "Postal Service", "Definitely Postal Service" and anything that has text before "Postal Service". The `%` means "give anything that match 0 to many characters before this".
This will match "The Postal Service", "Postal Service", "Definitely Postal Service" and anything that has text before "Postal Service". The `%` means "give anything that matches 0 to many characters before this".

You can use multiple too. Let's say we wanted to know every band that had "Orchestra" in the name. We can do that with

Expand Down
4 changes: 2 additions & 2 deletions lessons/03-basic-sql/B-insert.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ This inserts a new artist into the Artist table. That table will have one column
INSERT INTO food (name, food_group, color) VALUES ('carrot', 'vegetable', 'orange'); -- notice the order is the same
```

Also note that here you could use double quotes (though I typically won't.)
Also, note that here you could use double quotes (though I typically won't.)

```sql
INSERT INTO "Artist" ("name") VALUES ('Radiohead');
Expand All @@ -43,7 +43,7 @@ One more update, let's change it to a different French techno group
UPDATE Artist SET name = 'Justice' WHERE name = 'Daft Punk' RETURNING *;
```

The returning allows you to basically SELECT the rows you're updating so you can see what changed.
The returning allows you to SELECT the rows you're updating so you can see what changed.

## DELETE

Expand Down
10 changes: 5 additions & 5 deletions lessons/03-basic-sql/C-tables.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ CREATE TABLE BandMember (

> SQLite has only four real data types: INTEGER, REAL, TEXT, and BLOB. It is a dynamically typed system. Therefore you can give datatypes like TINYINT but SQLite will just treat it like an INTEGER and likewise you can give a type of VARCHAR(255) but it will just treat it like TEXT (and therefore won't truncate it.) [See more here][types].
To see the table you created, run `.schema BandMember` in your psql instance to see it and the the sequence that you created. The sequence stores the `id` counter.
To see the table you created, run `.schema BandMember` in your psql instance to see it and the sequence that you created. The sequence stores the `id` counter.

We now have a table. A table is the actual repository of data. Think of a database like a folder and a table like a spreadsheet. You can have many spreadsheets in a folder. Same with tables.

Expand All @@ -26,7 +26,7 @@ Let's add a record to our table.
INSERT INTO BandMember (name, role) VALUES ('Thom Yorke', 'singer') RETURNING *;
```

This adds one row with a name of Thom Yorke and role of singer. Where is the id? Since we made it `PRIMARY KEY` it gets created automatically. Since this is the first item in our database, its ID will be `1`. As you have likely guessed already, the next item in the table will be `2`.
This adds one row with the name of Thom Yorke and the role of singer. Where is the id? Since we made it `PRIMARY KEY` it gets created automatically. Since this is the first item in our database, its ID will be `1`. As you have likely guessed already, the next item in the table will be `2`.

Let's see the record.

Expand Down Expand Up @@ -60,7 +60,7 @@ You can add multiple add a time as long as you comma separate them.

## ALTER TABLE

Okay so now we have a table again. What happens if we wanted to add a third field to our table? Let's add an `image` field that will point to a URL of an image of the person.
Okay so now we have a table again. What happens if we want to add a third field to our table? Let's add an `image` field that will point to a URL of an image of the person.

```sql
ALTER TABLE BandMember ADD COLUMN image TEXT;
Expand All @@ -72,14 +72,14 @@ Likewise we can drop it too:
ALTER TABLE BandMember DROP COLUMN image;
```

There's a lot of ways to alter a table. You can make it UNIQUE like we did or NOT NULL. You can also change the data type. For now let's add back our extra column.
There are a lot of ways to alter a table. You can make it UNIQUE like we did or NOT NULL. You can also change the data type. For now, let's add back our extra column.

```sql
ALTER TABLE BandMember
ADD COLUMN nationality TEXT NOT NULL DEFAULT 'UK';
```

Specifying a DEFAULT when using a NOT NULL constraint will prevent errors if the column has existing null values. In this case we're saying "add a new non null column, and for those that exist give them the value of 'UK'."
Specifying a DEFAULT when using a NOT NULL constraint will prevent errors if the column has existing null values. In this case, we're saying "add a new non-null column, and for those that exist give them the value of 'UK'."

> SQLite does not allow you to do multiple alterations in one statement. If you want to add multiple columns, you have to do multiple alter tables commands.
Expand Down
12 changes: 6 additions & 6 deletions lessons/04-intermediate-sql/A-relational-data.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
So far we've done a one to one matching of records. We've used a record in a database to represent one item: one band member, band, etc.
So far we've done a one-to-one matching of records. We've used a record in a database to represent one item: one band member, band, etc.

Now we're going to get into records that can relate to each other. Let's think about albums. A recipe has multiple ingredients. That **has** word is key here. It means there is a relationship. A single recipe has many ingredients. An ingredient can also be in many recipes. A tomato is both in pizza sauce and in a BLT. This is called a many-to-many relationship.

There's also one-to-many relationships, like imagine if we had multiple photos of each of our ingredients. A single ingredient will have five photos. And those photos will only will only belong to one ingredient. A photo of a green pepper doesn't make sense to belong to anything besides the green pepper ingredient.
There are also one-to-many relationships, like imagine if we had multiple photos of each of our ingredients. A single ingredient will have five photos. And those photos will only will only belong to one ingredient. A photo of a green pepper doesn't make sense to belong to anything besides the green pepper ingredient.

There can also exist one-to-one relationships but in general you would just make those the same record all together. You could split up the type and title into two tables, but why would you? Then you have a data sync problem. What if a band renames themselves? Ex: On a Friday → Radiohead, Prince → The Artist Formerly Known as Prince, The Quarrymen → The Beatles. Anyone that has ever tried to manually keep data in sync in two+ places knows eventually you will have issues.
There can also exist one-to-one relationships but in general, you would just make those the same record altogether. You could split up the type and title into two tables, but why would you? Then you have a data sync problem. What if a band renames themselves? Ex: On a Friday → Radiohead, Prince → The Artist Formerly Known as Prince, The Quarrymen → The Beatles. Anyone who has ever tried to manually keep data in sync in two+ places knows eventually you will have issues.

Luckily we can use relational data to have one table of bands, and one table of albums.
Luckily we can use relational data to have one table of bands and one table of albums.

```sql
SELECT * FROM Album LIMIT 5;
Expand Down Expand Up @@ -42,7 +42,7 @@ JOIN
LIMIT 5;
```

You can give tables aliases so they're easier to refer to. Some of the table names can get quite long so it's possible that this can make it more readable. In this case I'd argue that the single letter variable names make it _less_ readable, that's up to you.
You can give tables aliases so they're easier to refer to. Some of the table names can get quite long so this can make it more readable. In this case, I'd argue that the single-letter variable names make it _less_ readable, that's up to you.

## You can use WHERE!

Expand Down Expand Up @@ -78,7 +78,7 @@ WHERE
Album.Title LIKE '%live%';
```

As you can see, once you set up the JOIN and how you want to join the tables together, you can start filtering your results based on either table. The first query we askd for just Nirvana's albums, the second is just albums named `IV`, and the third we're asking for any album that `live` in it.
As you can see, once you set up the JOIN and how you want to join the tables together, you can start filtering your results based on either table. The first query we asked for only Nirvana's albums, the second is just albums named `IV`, and the third we're asking for any album that `live` in it.

## Joining more than two tables

Expand Down
Loading

0 comments on commit ca799f2

Please sign in to comment.