Compare commits

...

2 Commits

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

@ -7,6 +7,7 @@
| 3 | [MVP Pattern and Repositories](3-mvc-pattern-and-repositories.md) | [Download slides](3-mvc-pattern-and-repositories-slides.html?raw=1) | | 3 | [MVP Pattern and Repositories](3-mvc-pattern-and-repositories.md) | [Download slides](3-mvc-pattern-and-repositories-slides.html?raw=1) |
| 4 | [RESTful HTTP Methods](4-restful-http-methods.md) | [Download slides](4-restful-http-methods-slides.html?raw=1) | | 4 | [RESTful HTTP Methods](4-restful-http-methods.md) | [Download slides](4-restful-http-methods-slides.html?raw=1) |
| 5 | [Model Validation & API Design](5-model-validation-and-designing-apis.md) | [Download slides](5-model-validation-and-designing-apis-slides.html?raw=1) | | 5 | [Model Validation & API Design](5-model-validation-and-designing-apis.md) | [Download slides](5-model-validation-and-designing-apis-slides.html?raw=1) |
| 6 | [SQL](6-databases-with-entity-framework.md) | [Download slides](6-databases-with-entity-framework-slides.html?raw=1) | | | [SQL Databases](sql-databases.md) | [Download slides](sql-databases-slides.html?raw=1) |
| 6 | [Databases with Entity Framework](6-databases-with-entity-framework.md) | [Download slides](6-databases-with-entity-framework-slides.html?raw=1) |
| 7 | [Authentication & Authorization](7-authentication-and-authorization.md) | [Download slides](7-authentication-and-authorization-slides.html?raw=1) | | 7 | [Authentication & Authorization](7-authentication-and-authorization.md) | [Download slides](7-authentication-and-authorization-slides.html?raw=1) |
| 8 | [Testing](8-testing.md) | [Download slides](8-testing-slides.html?raw=1) | | 8 | [Testing](8-testing.md) | [Download slides](8-testing-slides.html?raw=1) |

@ -0,0 +1,96 @@
CREATE TABLE "users" (
"id" SERIAL PRIMARY KEY,
"full_name" varchar NOT NULL,
"email" varchar UNIQUE NOT NULL,
"created_at" timestamp NOT NULL
);
CREATE TABLE "genres" (
"id" SERIAL PRIMARY KEY,
"name" varchar UNIQUE NOT NULL
);
CREATE TABLE "languages" (
"id" SERIAL PRIMARY KEY,
"name" varchar UNIQUE NOT NULL
);
CREATE TABLE "books" (
"id" SERIAL PRIMARY KEY,
"name" varchar NOT NULL,
"release_year" int NOT NULL,
"genre_id" int NOT NULL,
"language_id" int NOT NULL
);
CREATE TABLE "volumes" (
"id" SERIAL PRIMARY KEY,
"book_id" int NOT NULL
);
CREATE TABLE "borrows" (
"id" SERIAL PRIMARY KEY,
"volume_id" int NOT NULL,
"user_id" int NOT NULL,
"borrowed_at" timestamp NOT NULL,
"due_date" timestamp NOT NULL,
"returned_at" timestamp
);
ALTER TABLE "books" ADD FOREIGN KEY ("genre_id") REFERENCES "genres" ("id");
ALTER TABLE "books" ADD FOREIGN KEY ("language_id") REFERENCES "languages" ("id");
ALTER TABLE "volumes" ADD FOREIGN KEY ("book_id") REFERENCES "books" ("id");
ALTER TABLE "borrows" ADD FOREIGN KEY ("volume_id") REFERENCES "volumes" ("id");
ALTER TABLE "borrows" ADD FOREIGN KEY ("user_id") REFERENCES "users" ("id");
INSERT INTO users (full_name, email, created_at)
VALUES
('Teppo Testaaja', 'teppo.testaaja@buutti.com', NOW()),
('Taija Testaaja', 'taija.testaaja@buutti.com', NOW()),
('Outi Ohjelmoija', 'outi.ohjelmoija@buutti.com', NOW()),
('Olli Ohjelmoija', 'olli.ohjelmoija@buutti.com', NOW());
INSERT INTO genres (name)
VALUES
('Scifi'),
('Fantasy'),
('Comic book'),
('Horror'),
('Drama');
INSERT INTO languages (name)
VALUES
('Finnish'),
('English'),
('Swedish');
INSERT INTO books (name, release_year, genre_id, language_id)
VALUES
('Taru Sormusten Herrasta', 1954, 2, 1),
('Silmarillion', 1977, 2, 2),
('The Hitchhikers Guide to the Galaxy', 1979, 1, 2);
INSERT INTO volumes (book_id)
VALUES
(1),
(1),
(1),
(1),
(1),
(1),
(2),
(2),
(2),
(3),
(3);
INSERT INTO borrows (volume_id, user_id, borrowed_at, due_date, returned_at)
VALUES
(1, 1, current_timestamp - (30 * interval '1 day'), current_timestamp, null),
(2, 2, current_timestamp - (35 * interval '1 day'), current_timestamp - (5 * interval '1 day'), null),
(7, 1, current_timestamp - (40 * interval '1 day'), current_timestamp - (10 * interval '1 day'), current_timestamp - (15 * interval '1 day'));

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 66 KiB

File diff suppressed because one or more lines are too long

@ -0,0 +1,400 @@
---
marp: true
paginate: true
math: mathjax
theme: buutti
title: SQL Databases
---
# SQL Databases
<!-- headingDivider: 5 -->
<!-- class: invert -->
## What is SQL?
* SQL, Structured Query Language is a language used to organize and manipulate data in a database
* Originally developed by IBM in the 70's
* Quickly became the most popular database language
```sql
SELECT id, email
FROM users
WHERE first_name = 'Teppo';
```
## Relational Database Management Systems
* In relational databases, values are stored in *__tables__*
* Each table has *__rows__* and *__columns__*
* Data is displayed in a two-dimensional matrix
* Values in a table are related to each other
* Values can also be related to values in other tables
* A relational database management system (RDBMS) is a program that executes queries to relational databases
---
![](imgs/7-databases-with-entity-framework_0.png)
[https://db-engines.com/en/ranking](https://db-engines.com/en/ranking)
## PostgreSQL
* Free and open-source, cross-platform relational database management system
* Emphasizes extensibility and SQL compliance
* Fully ACID-compliant (atomicity, consistency, isolation and durability)
* Used in conjunction with ***pgAdmin***
* Administration and development platform for PostgreSQL
* Cross-platform, features a web interface
* Basically a control panel application for your PostgreSQL database
### PostgreSQL: Creating a Database
<div class='columns' markdown='1'>
<div markdown='1'>
With pgAdmin:
1) Right-click *Servers > my-postgres > Databases*
2) Select _Create > Database..._
3) Insert a name for the database and hit _Save_
</div>
<div markdown='1'>
With psql:
1) Enter command
```sql
CREATE DATABASE <database-name>;
```
</div>
</div>
<div class='centered'>
![](imgs/7-databases-with-entity-framework_1.png)
</div>
### PostgreSQL: Querying
With pgAdmin:
1) Right-click _sqlpractice > Query tool..._
2) Insert a query into the _Query Editor_ and hit _Execute_ (F5)
<div class='columns23' markdown='1'>
<div markdown='1'>
![w:345](imgs/7-databases-with-entity-framework_2.png)
</div>
<div markdown='1'>
![](imgs/7-databases-with-entity-framework_3.png)
</div>
</div>
---
With psql:
1) List all available databases with `\l`
2) Connect to the created database with `\c <database-name>`
3) List all tables in the database with `\dt`
4) Type a query and press enter
* Here's an [example query](code-examples/example-query.sql)
## Editing Data with pgAdmin
<div class='columns' markdown='1'>
<div markdown='1'>
* Inspect and edit data in pgAdmin by right-clicking a table and selecting _View/Edit Data_
</div>
<div markdown='1'>
![](imgs/7-databases-with-entity-framework_4.png)
</div>
</div>
---
<div class='columns' markdown='1'>
<div markdown='1'>
* Individual values in the table can be directly modified by double clicking the value and then editing the value in the visual user interface
* Save the changes by pressing the _Save Data Changes_ button
</div>
<div markdown='1' class='centered'>
![](imgs/7-databases-with-entity-framework_5.png)
![](imgs/7-databases-with-entity-framework_6.png)
</div>
</div>
## Exercise 1: Preparing the database
<!--_class: "exercise invert" -->
Using either PgAdmin or PSQL,
1) Create a new database called `sqlpractice`
2) Insert the provided [example query](code-examples/example-query.sql) to the new database
3) Verify that the query has created new tables to your database
## Basic SQL queries
* `SELECT`
* `INSERT`
* `DELETE`
* `UPDATE`
* `CREATE` & `DROP`
### Querying data with `SELECT`
* Syntax:
```sql
SELECT column1, column2, column3 FROM table_name;
```
* Examples:
```sql
SELECT full_name, email FROM users;
SELECT full_name AS name, email FROM users;
SELECT * FROM users;
```
### Filtering data with `WHERE`
* Syntax:
```sql
SELECT column1, column2 FROM table_name WHERE condition;
```
<div class='columns12' markdown='1'>
<div markdown='1'>
* Text is captured in **_single quotes_**.
* `LIKE` condition uses the `%` sign as a wildcard.
* `IS` and `IS NOT` are also valid operators.
</div>
<div markdown='1'>
* Example:
```sql
SELECT full_name FROM users
WHERE full_name = 'Teppo Testaaja';
SELECT * FROM books WHERE name LIKE '%rr%';
SELECT * FROM books WHERE author IS NOT null;
```
</div>
</div>
### Ordering data with `ORDER BY`
* Syntax:
```sql
SELECT column1 FROM table_name ORDER BY column1 ASC;
```
* Examples:
```sql
SELECT full_name FROM users
ORDER BY full_name ASC;
SELECT full_name FROM users
ORDER BY full_name DESC;
```
### Combining data with `JOIN`
* Also known as `INNER JOIN`
* Corresponds to ***intersection*** from [set theory](https://en.wikipedia.org/wiki/Set_theory)
<div class='centered'>
![w:500px](imgs/7-databases-with-entity-framework_7.png)
</div>
#### JOIN examples
```sql
SELECT
users.id, users.full_name, borrows.id,
borrows.user_id, borrows.due_date, borrows.returned_at
FROM users
JOIN borrows ON
users.id = borrows.user_id;
```
```sql
SELECT
U.full_name AS name,
B.due_date AS due_date,
B.returned_at AS returned_at
FROM users AS U
JOIN borrows AS B ON
U.id = B.user_id;
```
### Combining with `LEFT JOIN`
<div class='columns' markdown='1'>
<div markdown='1'>
* Also known as `LEFT OUTER JOIN`
* Example:
```sql
SELECT
U.full_name AS name,
B.due_date AS due_date,
B.returned_at AS returned_at
FROM users AS U
LEFT JOIN borrows AS B ON
U.id = B.user_id;
```
</div>
<div markdown='1'>
![](imgs/7-databases-with-entity-framework_8.png)
</div>
</div>
### Exercise 2: Querying the library
<!--_class: "exercise invert" -->
Using SQL queries, get
1) all columns of `borrows` that are borrowed before `2020-10-27`
2) all columns of `borrows` that are returned
3) columns `user.full_name` and `borrows.borrowed_at` of the user with an `id` of 1
4) columns `book.name`, `book.release_year` and `language.name` of all books that are released after 1960
### Inserting data with `INSERT`
* Syntax
```sql
INSERT INTO table_name (column1, column2, column3) VALUES (value1, value2, value3);
```
* Example
```sql
INSERT INTO users (full_name, email, created_at)
VALUES ('Pekka Poistuja', 'pekka.poistuja@buutti.com', NOW());
```
* Since id is not provided, it will be automatically generated.
### Updating data with `UPDATE`
* Syntax
```sql
UPDATE table_name SET column1 = value1, column2 = value2 WHERE condition;
```
* *__Notice:__* if a condition is not provided, all rows will be updated!
* If updating only one row, it is usually best to use `id`.
* Example
```sql
UPDATE users SET email = 'taija.testaaja@gmail.com' WHERE id = 2;
```
## Removing data with `REMOVE`
* Syntax
```sql
DELETE FROM table_name WHERE condition;
```
* Again, if the _condition_ is not provided, `DELETE` affects _all_ rows
* Before deleting, it is a good practice to execute an equivalent `SELECT` query to make sure that only the proper rows will be affected.
* Example:
```sql
SELECT * FROM users WHERE id = 5;
DELETE FROM users WHERE id = 5;
```
### Exercise 3: Editing data
<!--_class: "exercise invert" -->
1) Postpone the due date of the borrow with an `id` of `1` by two days in the `borrows` table
2) Add a couple of new books to the `books` table
3) Delete one of the borrows.
### Initializing data with `CREATE TABLE`
* Before data can be manipulated, a database and its tables need to be initialized.
<div class='columns' markdown='1'>
<div markdown='1'>
* Syntax
```sql
CREATE TABLE table_name (
column1 datatype,
column2 datatype,
...
);
```
</div>
<div markdown='1'>
* Example:
```sql
CREATE TABLE "users" (
"id" SERIAL PRIMARY KEY,
"full_name" varchar NOT NULL,
"email" varchar UNIQUE NOT NULL,
"created_at" timestamp NOT NULL
);
```
</div>
</div>
### Removing data with `DROP`
* In order to remove tables or databases, we use a `DROP` statement
```sql
DROP TABLE table_name;
DROP DATABASE database_name;
```
* These statements do not ask for confirmation and there is no undo feature. Take care when using a drop statement.
---
* I'm legally obliged to include this XKCD comic here.
![](https://imgs.xkcd.com/comics/exploits_of_a_mom_2x.png)
## NoSQL
* In addition to SQL databases, there's ***NoSQL***
* There are many differing definitions, but...
* most agree that NoSQL databases store data in a format other than tables
* They can still store relational data - just _differently_
* Four different database types:
* Document databases
* Key-value databases
* Wide-column stores
* Graph databases
* Example database engines include [MongoDB](https://www.mongodb.com/), [Redis](https://redis.io/) and [Cassandra](https://cassandra.apache.org/_/index.html)
* For more info, see [MongoDB: What is NoSQL?](https://www.mongodb.com/resources/basics/databases/nosql-explained)
## Object-Relational Mappers
* Object-Relational Mappers, or ORMs allow the developer to write code instead of SQL to perform CRUD operations on their database
* An abstraction layer between code and database
* Can make database logic easier to read and write
* Prevents SQL injection by sanitizing input (see the comic before...)
* ...but sometimes you'd rather just write the SQL queries themselves
* Some popular ORMs:
* Hibernate (Java)
* EFCore (.NET)
* Sequelize (Node.js)
* TypeORM (TypeScript)
Loading…
Cancel
Save