SQL Oppimiskeskus

Kehitä SQL taitojasi selkeästi ja tehokkaasti

Opi SQL:n perusteet ja edistyneet tekniikat, PostgreSQL:n käyttö sekä ero relaatio- ja dokumenttitietokantojen välillä. Käytännönläheisiä esimerkkejä opiskelijoille, opettajille ja kehittäjille.

Perusteet

Mikä on SQL?

SQL (Structured Query Language) on standardoitu kieli relaatiotietokantojen hallintaan ja käsittelyyn. SQL:llä voit:

Hakea tietoja

Käytä SELECT-lauseita etsiäksesi ja suodattaaksesi tietoja tietokannoista.

Muokata tietoja

INSERT, UPDATE ja DELETE komennoilla lisäät, päivität ja poistat tietoja.

Luoda rakenteita

CREATE TABLE ja ALTER TABLE komennoilla luot ja muokkaat tietokantarakenteita.

Yhdistää tauluja

JOIN-operaatioilla yhdistät useita tauluja monimutkaisiin kyselyihin.

Kyselyt

SQL Kyselyt

SQL-kyselyt ovat tietokannan sydän. Niillä haet, suodatat ja järjestelet tietoja tehokkaasti.

SELECT

Peruskysely tietojen hakemiseen:

sql — select
SELECT name, email
FROM users;

WHERE

Suodata tuloksia ehtojen perusteella:

sql — where
SELECT *
FROM users
WHERE age > 18;

JOIN

Yhdistä useita tauluja:

sql — join
SELECT u.name, o.total
FROM users u
JOIN orders o ON u.id = o.user_id;

GROUP BY

Ryhmittele ja laske:

sql — group by
SELECT city, COUNT(*) AS user_count
FROM users
GROUP BY city;
Hallinta

Tietojen hallinta

SQL:llä voit paitsi hakea tietoja, myös lisätä, muokata ja poistaa niitä turvallisesti.

INSERT - Tietojen lisääminen

Lisää uusi rivi tauluun:

sql — insert
-- Lisää uusi käyttäjä
INSERT INTO users (name, email, age)
VALUES ('Matti Meikäläinen', 'matti@example.com', 25);

UPDATE - Tietojen muokkaaminen

Päivitä olemassa olevia rivejä:

sql — update
-- Päivitä käyttäjän sähköposti
UPDATE users
SET email = 'uusi.sahkoposti@example.com'
WHERE id = 1;

DELETE - Tietojen poistaminen

Poista rivejä ehdon perusteella:

sql — delete
-- Poista pitkään kirjautumattomat käyttäjät
DELETE FROM users
WHERE last_login < '2023-01-01';

Turvallisuusvinkkejä

  • Käytä aina WHERE-ehtoa UPDATE- ja DELETE-komennoissa
  • Tee varmuuskopio ennen suuria muutoksia
  • Testaa kyselyt ensin pienellä datajoukolla
  • Käytä transaktioita kriittisissä operaatioissa
Tietokanta

PostgreSQL

PostgreSQL on tehokas, avoimen lähdekoodin relaatiotietokantajärjestelmä, joka noudattaa SQL-standardia mutta tarjoaa lukuisia laajennuksia ja parannuksia.

PostgreSQL vs SQL-standardi

SQL-standardi (ISO/IEC 9075)

Standardi määrittelee kielen ytimen:

  • SELECT, INSERT, UPDATE, DELETE
  • Perusdatatyypit (VARCHAR, INTEGER, DATE)
  • JOIN-operaatiot
  • Rajoitteet: PRIMARY KEY, FOREIGN KEY, CHECK
  • Transaktiot ja eristystasot
  • Window functions ja CTE:t (SQL:2003 ja SQL:1999)

PostgreSQL:n laajennukset

PostgreSQL lisää standardin päälle:

  • Kehittyneet datatyypit: JSONB, taulukot, UUID, range- ja geometriatyypit
  • Indeksityypit: GIN, GiST, BRIN ja osittaiset indeksit
  • Perintä ja partitiointi: Taulut voivat periä toisista tauluista
  • Laajennukset: PostGIS (paikkatiedot), pg_trgm, pgvector
  • Full-text search: Sisäänrakennettu tekstihaku ilman erillistä hakukonetta

PostgreSQL vs MySQL

MySQL 8.0 toi mukanaan window functionsit ja CTE:t, joten ero ei ole enää niissä. PostgreSQL erottuu edelleen JSONB-tuella, monipuolisemmilla indeksityypeillä ja laajennusekosysteemillä.

Standardin noudattaminen

Kaikki suuret järjestelmät (PostgreSQL, MySQL, SQL Server, Oracle) noudattavat SQL-standardia, mutta lisäävät omia laajennuksiaan. Siksi kyselyt eivät aina siirry sellaisenaan järjestelmästä toiseen.

Käytännön esimerkit

Standardi SQL-kysely

Toimii kaikissa SQL-tietokannoissa:

sql — standard
SELECT name, email, age
FROM users
WHERE age > 25
ORDER BY name;

PostgreSQL-erityisominaisuus

JSONB-datan käsittely PostgreSQL:n operaattoreilla:

sql — postgresql
-- ->> palauttaa tekstiä, joten ilman ::int
-- vertailtaisiin merkkijonoina, jolloin
-- '9' > '25' olisi tosi
SELECT name,
  profile->>'city' AS city,
  profile->'preferences' AS prefs
FROM users
WHERE (profile->>'age')::int > 25;

Miksi valita PostgreSQL?

Yrityskäyttö

  • Instagram (pääasiallinen tietokanta)
  • Reddit (kommentit ja postaukset)
  • Booking.com (varausjärjestelmä)
  • Supabase ja Heroku Postgres (alustapalvelut)

Tekninen etu

  • Monipuoliset datatyypit
  • Kehittyneet indeksityypit
  • MVCC-pohjainen rinnakkaisuus
  • Laaja laajennusekosysteemi

Käyttötapaukset

  • Web-sovellukset (JSONB-data)
  • Analytiikka ja BI
  • Paikkatietosovellukset (PostGIS)
  • Verkkokaupat
Vertailu

MongoDB vs SQL

SQL (Relaatiotietokannat)

  • Rakenne: Taulut, rivit, sarakkeet
  • Skeema: Ennalta määritelty ja tiukka
  • Kyselykieli: SQL
  • ACID: Täysi tuki
  • Skaalautuvuus: Pystysuora skaalaus, lukureplikat ja partitiointi; vaakasuora skaalaus vaatii lisätyökaluja
  • Esimerkit: PostgreSQL, MySQL, SQLite

MongoDB (Dokumenttitietokanta)

  • Rakenne: Kokoelmat ja dokumentit (JSON/BSON)
  • Skeema: Joustava ja dynaaminen
  • Kyselykieli: MongoDB Query API
  • ACID: Yksittäinen dokumentti aina atominen; monen dokumentin transaktiot 4.0:sta (sharded 4.2:sta)
  • Skaalautuvuus: Vaakasuora skaalaus sisäänrakennetulla shardingilla
  • Esimerkit: MongoDB, CouchDB, Amazon DocumentDB

Esimerkkikysely

sql — join
-- Yhdistä käyttäjät ja heidän
-- postauksensa yhdellä kyselyllä
SELECT u.name, u.email, p.title
FROM users u
JOIN posts p ON u.id = p.user_id
WHERE u.age > 25;
mongodb — aggregate
db.users.aggregate([
  { $match: { age: { $gt: 25 } } },
  { $lookup: {
      from: "posts",
      localField: "_id",
      foreignField: "userId",
      as: "posts"
  } }
]);

Milloin käyttää kumpaakin?

SQL soveltuu parhaiten

  • Pankkisovellukset: Transaktiot, ACID-vaatimukset
  • ERP-järjestelmät: Rakenteelliset liiketoimintatiedot
  • Verkkokaupat: Tilaukset, asiakastiedot, varastot
  • CRM-järjestelmät: Asiakashallinta
  • Raportointi: Analytiikka ja BI
  • Kirjanpito: Tarkka tietojen eheys

Esimerkkiyrityksiä: PayPal, Booking.com, Instagram, verkkopankit

MongoDB soveltuu parhaiten

  • Sisällönhallinta: Joustavat rakenteet
  • IoT-sovellukset: Vaihtelevan muotoinen sensoridata
  • Tapahtumalokit: Suuret kirjoitusmäärät
  • Reaaliaikainen analytiikka: Suuret datamäärät
  • Prototyypit: Nopea kehitys ilman migraatioita
  • Tuoteluettelot: Tuotteet vaihtelevilla ominaisuuksilla

Esimerkkiyrityksiä: Adobe, eBay, Forbes, Toyota Connected

Suorituskyky

OminaisuusSQLMongoDB
LukutoiminnotOptimoitu monimutkaisille kyselyilleNopea, kun data haetaan yhtenä dokumenttina
KirjoitustoiminnotACID-takuut lisäävät kustannustaNopeampi, kun rajoitteita on vähemmän
LiitoksetJOIN on kypsä ja optimoitu$lookup on raskaampi kuin JOIN
IndeksointiKypsä teknologia, useita indeksityyppejäJoustava, mutta suunnittelu on työläämpää
SkaalautuvuusReplikointi ja partitiointi; sharding laajennuksilla (esim. Citus)Sisäänrakennettu automaattinen sharding

Kumpi valita projektiin?

Valitse SQL jos
  • Tarvitset vahvat ACID-takuut
  • Data on rakenteellista
  • Teet monimutkaisia kyselyitä
  • Rakennat taloudellista sovellusta
Valitse MongoDB jos
  • Tarvitset joustavan datamallin
  • Kehität prototyyppiä nopeasti
  • Skaalaat vaakasuunnassa
  • Data on dokumenttimuotoista
Voit käyttää molempia
  • Hybridiarkkitehtuuri
  • SQL analytiikkaan
  • MongoDB reaaliaikaiseen dataan
  • Mikropalveluarkkitehtuuri
Turvallisuus

Turvallisuusnäkökulma

SQL-injektio

SQL-tietokantojen tunnetuin turvallisuusriski:

Haavoittuva koodi

vulnerable — sql injection
// Syöte liitetään suoraan kyselyyn
const sql =
  "SELECT * FROM users WHERE name = '" +
  userInput + "'";
await db.query(sql);

// userInput = "'; DROP TABLE users; --"
// tuhoaa koko taulun

Turvallinen ratkaisu

secure — parameterized
// Parametroitu kysely: syöte ei ole
// koskaan osa SQL-lausetta
const sql =
  'SELECT * FROM users WHERE name = $1';
await db.query(sql, [userInput]);

// Tietokanta käsittelee arvon
// aina datana, ei koodina

NoSQL-injektio

Sama ongelma dokumenttitietokannassa:

Haavoittuva koodi

vulnerable — nosql injection
// $where suorittaa JavaScriptiä
// palvelimella
db.users.find({ $where: userInput });

// Objektisyöte ohittaa myös
// tavallisen vertailun:
db.users.find({ name: userInput });
// { $ne: null } palauttaa kaikki rivit

Turvallinen ratkaisu

secure — typed query
// Pakota syöte merkkijonoksi
// ja vältä $where
if (typeof userInput !== 'string') {
  throw new Error('invalid input');
}
db.users.find({ name: userInput });

// Skeemavalidointi torjuu operaattorit

Yleisiä turvallisuuskäytäntöjä

  • Validoi kaikki käyttäjäsyötteet
  • Käytä pienimmän oikeuden periaatetta
  • Salaa tiedot levyllä ja siirron aikana
  • Tee säännölliset tietoturva-auditoinnit
  • Rajoita tietokannan verkkoyhteydet
  • Päivitä järjestelmät säännöllisesti
  • Käytä monivaiheista tunnistautumista
  • Lokita ja monitoroi tietokannan käyttöä
ORM

Prisma & ORM

ORM (Object-Relational Mapping) yhdistää ohjelmointikielen objektit tietokantakyselyihin. Prisma on moderni TypeScript/JavaScript ORM, joka kääntää koodisi SQL-komennoiksi automaattisesti.

Ennen: perinteinen SQL

traditional — javascript
// Käsin kirjoitettu SQL
const sql =
  'SELECT * FROM users WHERE age > $1';
const results = await db.query(sql, [18]);
// Tulos on tyypittämätön

Jälkeen: Prisma ORM

prisma — typescript
// Prisma: tyypitetty kysely
const adults = await prisma.user.findMany({
  where: { age: { gt: 18 } }
});
// adults on tyyppiä User[]

Ongelmat: kirjoitusvirheet paljastuvat vasta ajossa, eikä editori tunne tulosrivin muotoa.

Etu: kääntäjä tarkistaa kentät ja editori osaa täydentää ne automaattisesti.

Kuinka Prisma toimii?

1. Schema

Kuvaat datamallin Prisman schema-tiedostossa

2. Generate

Prisma generoi TypeScript-tyypit ja client-koodin

3. SQL-käännös

Ajossa Prisma kääntää metodikutsut SQL-kyselyiksi

Prisma tukee: PostgreSQL, MySQL, SQLite, SQL Server, CockroachDB, MongoDB

Esimerkit

Käytännön SQL-esimerkit

1. Perushaku

Suodata ja järjestä tulokset:

sql — query
-- Hae kaikki yli 18-vuotiaat käyttäjät
SELECT name, email, age
FROM users
WHERE age > 18
ORDER BY name;

2. Taulujen yhdistäminen

Hae rivejä kahdesta taulusta yhdellä kyselyllä:

sql — join
-- Hae käyttäjät ja heidän tilauksensa
SELECT u.name, u.email, o.order_date, o.total
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE o.order_date > '2024-01-01';

3. Ryhmittely ja laskenta

LEFT JOIN säilyttää myös asiakkaat, joilla ei ole yhtään tilausta:

sql — aggregate
-- Laske tilausten määrä ja kokonaissumma asiakkaittain
SELECT u.name,
       COUNT(o.id) AS order_count,
       COALESCE(SUM(o.total), 0) AS total_spent
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.name
ORDER BY total_spent DESC;

SQL Oppimiskeskus

Ilmainen opetusresurssi SQL:n, PostgreSQL:n ja tietokantojen oppimiseen. Suunniteltu opiskelijoille ja opettajille.

Kaikki esimerkit ja oppimateriaali on tarkoitettu opetuskäyttöön. Sisältö on avointa ja vapaasti käytettävissä.

Tämä sivusto voi sisältää virheitä - tarkista aina tiedot virallisista lähteistä.

Lue lisää SQL:stä
Tietoa

SQL Oppimiskeskus

Opi SQL:ää helposti

Kattava oppimisalusta SQL:n perusteista edistyneisiin tekniikoihin. Sopii opiskelijoille ja oppilaitoksille.