# Opi SQL:ää – opas, jossa on koodiesimerkkejä

SQL:n syntaksi perustuu **relaatioalgebraan**, mikä erottaa tämän ohjelmointikielen muista kielistä. Syntaksin opettelu käytännön esimerkkien avulla voi auttaa sinua oppimaan SQL:ää tehokkaasti.

## Mikä on SQL-syntaksi?

Ohjelmoinnissa syntaksi tarkoittaa sitä, **miten ohjelmointikieli kirjoitetaan**. Syntaksi määrittelee koodin perusrakenteet ja niiden yhdistämistavat. Syntaksin ymmärtäminen on ohjelmointikielillä koodin lukemisen ja kirjoittamisen perusedellytys.

SQL:n tärkeimmät syntaksirakenteet ovat **SQL-lauseet, jotka voivat sisältää myös lauseosia**. Molempia kutsutaan yleisesti ”SQL-komennoiksi”, vaikka teknisesti katsoen tämä ei olekaan täysin tarkka ilmaisu. Nämä eivät kuitenkaan ole ainoat SQL-syntaksirakenteet. Alla olevasta taulukosta löydät yleiskatsauksen SQL-syntaksirakenteista.

<table>
  <thead>
    <tr>
      <th><strong>SQL-termi</strong></th>
      <th><strong>Selitys</strong></th>
      <th><strong>Esimerkki</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Lause</td>
      <td>Käskee DBMS:ää suorittamaan toiminnon; päättyy puolipisteeseen</td>
      <td>`CREATE TABLE People;`</td>
    </tr>
    <tr>
      <td>Lause</td>
      <td>Muokkaa lausetta; voi esiintyä vain lauseiden sisällä</td>
      <td>`WHERE, HAVING`</td>
    </tr>
    <tr>
      <td>Lauseke</td>
      <td>Palauttaa arvon arvioitaessa</td>
      <td>`6 * 7`</td>
    </tr>
    <tr>
      <td>Tunniste</td>
      <td>Tietokantaobjektin, muuttujan tai proseduurin nimi; voi olla määritelty tai määrittelemätön</td>
      <td>`dbname.tablename / tablename`</td>
    </tr>
    <tr>
      <td>Predikaatti</td>
      <td>Lauseke, jonka arvo on `TRUE, FALSE` tai `UNKNOWN`</td>
      <td>`Age < 42`</td>
    </tr>
    <tr>
      <td>Kysely</td>
      <td>Erityinen lause; palauttaa löydetyt tietueet</td>
      <td>`SELECT Name FROM People WHERE Age < 42;`</td>
    </tr>
    <tr>
      <td>Funktio</td>
      <td>Käsittelee yhtä tai useampaa arvoa; luo yleensä uuden arvon</td>
      <td>`UPPER('text') -- returns 'TEXT'`</td>
    </tr>
    <tr>
      <td>Kommentti</td>
      <td>Käytetään SQL-koodin kommentointiin; RDBMS ohittaa sen</td>
      <td>`-- Comment up to end of line / /*multiline comment if necessary*/`</td>
    </tr>
  </tbody>
</table>

Huomio SQL-komennot, kuten SELECT ja CREATE TABLE, kirjoitetaan yleensä isoilla alkukirjaimilla. SQL ei kuitenkaan erota isoja ja pieniä kirjaimia. Komentojen kirjoittaminen isoilla alkukirjaimilla on vain yleisesti käytetty käytäntö.

## Miten SQL-koodi suoritetaan?

SQL-koodi on lähdekoodina tekstitiedostoissa. Koodi herää eloon vasta sopivassa suoritusympäristössä. **SQL-tulkki** lukee lähdekoodin ja muuntaa sen RDBMS-järjestelmän toiminnoiksi. Tässä on kaksi peruslähestymistapaa:

**1. Suorita SQL-koodi**interaktiivisesti Tässä menetelmässä SQL-koodi syötetään tai kopioidaan suoraan tekstiruutuun. SQL-koodi suoritetaan, ja tulos näytetään. Voit muokata koodia ja suorittaa sen uudelleen. Koodin muokkaamisen ja tulosten näyttämisen nopea vuorottelu tekee tästä menetelmästä parhaiten sopivan monimutkaisten kyselyjen oppimiseen ja luomiseen. **2. Suorita SQL-koodi skriptinä**Tässä menetelmässä koko SQL-koodia sisältävä lähdekooditiedosto suoritetaan rivi riviltä. Tarvittaessa palautetta lähetetään käyttäjälle vasta suorituksen lopussa. Tämä menetelmä sopii parhaiten prosessien automatisointiin ja MySQL-tietokantavarmuuskopioiden tuontiin MySQL-dump-komennolla.

<table>
  <thead>
    <tr>
      <th><strong>Käyttöliittymä</strong></th>
      <th><strong>Kuvaus</strong></th>
      <th><strong>Esimerkkejä</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Komentoriviliitäntä (CLI)</td>
      <td>Tekstipohjainen käyttöliittymä; SQL-koodi syötetään ja suoritetaan, tulos näytetään tekstinä</td>
      <td>mysql, psql, mysqlsh</td>
    </tr>
    <tr>
      <td>Graafinen käyttöliittymä (GUI)</td>
      <td>SQL-koodi syötetään teksti-ikkunaan ja/tai generoidaan käyttäjän toimien perusteella; SQL-koodi suoritetaan, tulos näytetään taulukoina</td>
      <td>phpMyAdmin, MySQL Workbench, HeidiSQL</td>
    </tr>
    <tr>
      <td>Sovellusohjelmointirajapinta (API)</td>
      <td>Mahdollistaa suoran viestinnän RDBMS:n kanssa; SQL-koodi sisällytetään ja suoritetaan merkkijonona ohjelmointikielen koodissa; tulokset ovat käytettävissä tietorakenteina jatkokäyttöä varten</td>
      <td>PHP Data Objects (PDO), Connector/J (Java), Connector/Python, C API</td>
    </tr>
  </tbody>
</table>

## Tuotehallintajärjestelmän määrittäminen SQL:n avulla

Helpoin tapa oppia ohjelmointikieltä on kirjoittaa ja suorittaa koodia itse. Tässä opetusohjelmassa **luomme pienen tietokannan ja teemme siihen kyselyjä**. Tätä varten käytämme verkkosivuston *sql.js* tarjoamaa [online-SQL-tulkkia](https://sql.js.org/examples/GUI/ "sql.js demo: Online SQL interpreter"). Voit seurata opetusohjelmaa siirtymällä sivustolle ja korvaamalla sinne jo syötetyn SQL-koodin esimerkkien koodilla. Suorita koodi pala palalta, jotta tulokset tulevat näkyviin.

### Luo SQL-tietokanta

Tässä esimerkissä rakennamme kaupallisen **tuotanhallintajärjestelmän** eräälle kaupalle. Vaatimukset ovat seuraavat:

- Tuotteita on useita, ja jokaisesta tuotteesta on varastossa tietty määrä.
- Asiakaskuntaamme kuuluu monia asiakkaita.
- Asiakkaiden tekemät tilaukset voivat sisältää useita tuotteita.
- Jokaisesta tilauksesta tallennamme tilauspäivän ja tilaajan tiedot sekä tilatut tuotteet ja tilausmäärän.

Nämä vaatimukset muunnetaan **abstraktiksi kuvauksiksi ja sen jälkeen SQL-koodiksi**:

1. Luo malli
2. Määritä skeema
3. Syötä tietueet
4. Määritä kyselyt

### Luo malli entiteeteistä ja suhteista

Ensimmäinen vaihe toteutetaan paperilla tai erityisillä mallinnustyökaluilla. Keräämme tietoa **mallinnettavasta** järjestelmästä, **jotta voimme määrittää entiteetit ja suhteet**. Tämä vaihe toteutetaan usein entiteetti-suhdekaaviona (ER-kaaviona).

Mitä entiteettejä on olemassa ja miten ne liittyvät toisiinsa? **Entiteetit ovat asioiden luokkia**. Tuotehallintajärjestelmän esimerkissämme entiteettejä ovat tuotteet, asiakkaat ja tilaukset. Jokaista entiteettiä varten tarvitaan oma taulukko. Relaatiomallin erityispiirteiden vuoksi suhteiden mallintamiseksi lisätään uusia taulukoita. Tämän ymmärtäminen ja asianmukainen toteuttaminen vaatii kokemusta.

Keskeinen kysymys, johon on löydettävä vastaus, on se, miten entiteetit liittyvät toisiinsa. Tässä yhteydessä on otettava huomioon **suhteen molemmat suunnat** ja tehtävä ero **yksikön ja monikon** välillä. Seuraavassa on esimerkki, jossa käytetään autoja ja auton omistajia:

1. Yksi omistaja voi omistaa useita autoja.
2. Auto voi kuulua vain yhdelle omistajalle.

Näiden kahden tahon välillä voidaan havaita**kolme mahdollista suhdemallia**:

<table>
  <thead>
    <tr>
      <th><strong>Suhde</strong></th>
      <th><strong>Entiteetit</strong></th>
      <th><strong>Vasemmalta</strong></th>
      <th><strong>Oikealta</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1:1-suhde</td>
      <td>Auto:vilkku</td>
      <td>Autolla voi olla vain yksi vilkku.</td>
      <td>Yksi vilkku voi kuulua vain yhteen autoon.</td>
    </tr>
    <tr>
      <td>1:n-suhde</td>
      <td>Omistaja:auto</td>
      <td>Omistajalla voi olla useita autoja.</td>
      <td>Auto voi kuulua vain yhdelle omistajalle.</td>
    </tr>
    <tr>
      <td>m:n-suhde</td>
      <td>Auto:katu</td>
      <td>Auto voi ajaa useilla teillä.</td>
      <td>Useat autot voivat ajaa yhdellä tiellä.</td>
    </tr>
  </tbody>
</table>

### Tuotteiden käyttöönotto

Aluksi luomme tuotetietokannan. Tätä varten meidän on määriteltävä tietomalli, syötettävä tietueita ja suoritettava muutamia yksinkertaisia kyselyjä testausta varten.

#### Määritä skeema

Tietokantataulukoiden määrittämisen keskeinen SQL-komento on CREATE TABLE. Tämän komennon avulla voit **luoda taulukon, jolle annetaan nimi, ja määrittää sarakkeiden ominaisuudet**. Samalla määritellään tietotyypit ja tarvittaessa tallennettavia arvoja koskevat rajoitukset:

```sql
DROP TABLE IF EXISTS Products;
CREATE TABLE Products ( product_id int, product_name text, stocked int, price int );
```

Huomio Käytämme DROP TABLE IF EXISTS -lauseita ennen taulukon määrittelyä. Tämä poistaa mahdollisen olemassa olevan taulukon ja mahdollistaa saman SQL-koodin suorittamisen useita kertoja ilman, että siitä aiheutuu virheilmoituksia.

#### Lisää tietokokonaisuuksia

Luomme nyt muutaman **testitietueen**. Käytämme kenttien täyttämiseen SQL-komentoa INSERT INTO sekä VALUES-funktiota:

```sql
INSERT INTO Products VALUES (10, 'ABC Product', 74, 1050);
INSERT INTO Products VALUES (20, 'KLM Product', 23, 750);
INSERT INTO Products VALUES (30, 'XYZ Product', 104, 350);
```

#### Määritä kyselyt

**Tarkistaaksemme Products-taulukon tilan** kirjoitamme yksinkertaisen kyselyn. Käytämme SELECT FROM -komentoa ja tulostamme koko taulukon:

```sql
SELECT * FROM Products;
```

Nyt kirjoitamme hieman monimutkaisemman kyselyn, joka laskee **varastossamme olevien tuotteiden kokonaisarvon**:

```sql
SELECT product_name AS 'Name', (stocked * price) AS 'Value' FROM Products;
```

### Lisää taulukoita

Seuraavaksi **luomme loput tarvitsemamme taulukot**. Toimimme samalla tavalla kuin Tuotteet-taulukon kohdalla. Ensin luomme Asiakkaat-taulukon:

```sql
DROP TABLE IF EXISTS Customers;
CREATE TABLE Customers ( customer_id int, customer_name text, contact text );
```

Sitten syötämme kahden esimerkkiasiakkaan tiedot:

```sql
INSERT INTO Customers VALUES (100, 'EDC Customer', 'ED@example.com');
INSERT INTO Customers VALUES (200, 'WVU Customer', 'WV@example.com');
```

Tarkistaaksemme, toimiiko se, tulostamme asiakastiedoston:

```sql
SELECT * FROM Customers;
```

Seuraavaksi luodaan Orders-taulukko:

```sql
DROP TABLE IF EXISTS Orders;
CREATE TABLE Orders ( order_id int, customer_id int, order_date text );
```

**Syötämme** nyt **kolme esimerkkitilausta**. Ensimmäiseksi arvoksi määritämme tunnisteen (ID) ensisijaiseksi avaimeksi. Toinen arvo on olemassa olevien asiakastunnisteiden, jotka toimivat viiteavaimina. Sitten tallennamme tilauspäivän:

```sql
INSERT INTO Orders VALUES (1000, 100, '2022-05-03');
INSERT INTO Orders VALUES (1001, 100, '2022-05-04');
INSERT INTO Orders VALUES (1002, 200, '2022-05-08');
```

Testaamme sitä antamalla seuraavat komennot:

```sql
SELECT * FROM Orders;
```

Lopuksi tarvitsemme taulukon, joka **sisältää tilauksen tuotteet ja niiden määrät**. Kyseessä on m:n-suhde, koska yksi tilaus voi sisältää useita tuotteita ja yksi tuote voi esiintyä useissa tilauksissa. Määritellään taulukko, joka sisältää tilausten ja tuotteiden tunnisteet vierasavaimina:

```sql
DROP TABLE IF EXISTS OrderItems;
CREATE TABLE OrderItems ( orderitem_id int, order_id int, product_id int, count int );
```

Syötämme nyt muutaman tilatun tuotteen. Valitsemme tilausten ja tuotteiden tunnisteet siten, että yksi tilaus sisältää kaksi tuotetta ja toinen tilaus vain yhden tuotteen:

```sql
INSERT INTO OrderItems VALUES (10001, 1000, 10, 3);
INSERT INTO OrderItems VALUES (10002, 1000, 20, 2);
INSERT INTO OrderItems VALUES (10003, 1002, 30, 12);
```

Tarkistaaksemme tämän, toimitamme tilatut tuotteet:

```sql
SELECT * FROM OrderItems;
```

### Kirjoita monimutkaisia kyselyitä

Jos olet suorittanut kaikki tähän mennessä esitetyt koodinpätkät, sinun pitäisi pystyä ymmärtämään testitietokantamme rakenne. Siirrytään nyt monimutkaisempiin kyselyihin, jotka osoittavat SQL:n tehokkuuden. **Kirjoitetaan** ensin **kysely, joka yhdistää useisiin taulukoihin hajautetut tiedot**. Käytämme SQL JOIN -komentoa yhdistämään taulukot, jotka sisältävät asiakastiedot ja tilaukset. Samalla nimeämme sarakkeet ja asetamme vastaavan asiakastunnuksen JOIN-ehdoksi. Muista, että käytämme määriteltyjä tunnisteita erottamaan kahden taulukon sarakkeet toisistaan:

```sql
SELECT customers.customer_name as 'Customer', customers.customer_id, orders.order_id, orders.order_date AS 'Date' FROM Customers JOIN Orders ON Orders.customer_id = Customers.customer_id ORDER BY Customers.customer_id;
```

Nyt laskemme **tilattujen tuotteiden kokonaiskustannukset** toisen JOIN-komennon avulla:

```sql
SELECT OrderItems.order_id, OrderItems.orderitem_id AS 'Order Item', Products.product_name AS 'Product', Products.price AS 'Unit Price', OrderItems.count AS 'Count', (OrderItems.count * Products.price) AS 'Total' FROM OrderItems JOIN Products ON OrderItems.product_id = Products.product_id;
```

Vinkki Haluatko tietää lisää siitä, [mitä SQL on](https://www.ionos.com/fi-fi/digitalguide/palvelin/asetukset/sqln-esittely-esimerkkien-kera/), tai tarvitsetko apua tietokantakieleen liittyvän ongelman ratkaisemisessa? Tai ehkä haluat vain syventää SQL-osaamistasi. Olipa syy mikä tahansa, löydät digitaalisesta oppaastamme lukuisia artikkeleita SQL:stä ja MySQL:stä:

- MySQL-opas
- MariaDB vs. MySQL
- Kuinka asentaa ja käyttää MariaDB:tä/MySQL:ää
- Yhdistä MySQL-/MariaDB-tietokantaan PHP:llä Linux-pohjaisella pilvipalvelimella
- MySQL/MariaDB:n ”Too many connections” -virheen ratkaiseminen
- Kuinka nollata MySQL/MariaDB-pääkäyttäjän salasana


This is a markdown version of: [https://www.ionos.com/fi-fi/digitalguide/palvelin/asetukset/sqln-esittely-esimerkkien-kera/](https://www.ionos.com/fi-fi/digitalguide/palvelin/asetukset/sqln-esittely-esimerkkien-kera/) for AI/LLM consumption.