# Lær SQL – En veiledning med kodeeksempler

Syntaksen i SQL er basert på **relasjonsalgebra**, noe som skiller dette programmeringsspråket fra andre språk. Å gjøre deg kjent med syntaksen gjennom praktiske eksempler kan hjelpe deg med å lære SQL på en effektiv måte.

## Hva er SQL-syntaks?

I programmering refererer syntaks til **hvordan et programmeringsspråk skrives**. Syntaksen bestemmer de grunnleggende kodekonstruksjonene og hvordan de skal kobles sammen. Å forstå syntaksen er en grunnleggende forutsetning for å kunne lese og skrive kode i programmeringsspråk.

De viktigste syntakselementene i SQL er **SQL-setninger, som også kan inneholde klausuler**. Begge kalles ofte «SQL-kommandoer», selv om dette fra et teknisk synspunkt ikke er helt korrekt. Dette er imidlertid ikke de eneste syntakselementene i SQL. Nedenfor finner du en tabell som gir deg en oversikt over syntakselementene i SQL.

<table>
  <thead>
    <tr>
      <th><strong>SQL-begrep</strong></th>
      <th><strong>Forklaring</strong></th>
      <th><strong>Eksempel</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Setning</td>
      <td>Beordrer DBMS til å utføre en handling; avsluttes med et semikolon</td>
      <td>`CREATE TABLE People;`</td>
    </tr>
    <tr>
      <td>Klausul</td>
      <td>Modifiserer en setning; kan bare forekomme innenfor setninger</td>
      <td>`WHERE, HAVING`</td>
    </tr>
    <tr>
      <td>Uttrykk</td>
      <td>Returnerer en verdi ved evaluering</td>
      <td>`6 * 7`</td>
    </tr>
    <tr>
      <td>Identifikator</td>
      <td>Navnet på et databaseobjekt, en variabel eller en prosedyre; kan være kvalifisert eller ukvalifisert</td>
      <td>`dbname.tablename / tablename`</td>
    </tr>
    <tr>
      <td>Predikat</td>
      <td>Uttrykk som evalueres til `TRUE, FALSE` eller `UNKNOWN`</td>
      <td>`Age < 42`</td>
    </tr>
    <tr>
      <td>Spørring</td>
      <td>Spesiell setning; returnerer funnet sett med poster</td>
      <td>`SELECT Name FROM People WHERE Age < 42;`</td>
    </tr>
    <tr>
      <td>Funksjon</td>
      <td>Behandler en eller flere verdier; skaper vanligvis en ny verdi</td>
      <td>`UPPER('text') -- returns 'TEXT'`</td>
    </tr>
    <tr>
      <td>Kommentar</td>
      <td>Brukes til å kommentere SQL-kode; ignoreres av RDBMS</td>
      <td>`-- Comment up to end of line / /*multiline comment if necessary*/`</td>
    </tr>
  </tbody>
</table>

Note SQL-kommandoer som SELECT og CREATE TABLE skrives vanligvis med store bokstaver. SQL skiller imidlertid ikke mellom store og små bokstaver. Bruken av store bokstaver i kommandoer er bare en vanlig konvensjon.

## Hvordan utføres SQL-kode?

SQL-kode finnes som kildekode i tekstfiler. Koden blir først aktivert i et passende kjøringsmiljø. Kildekoden leses av en **SQL-tolker** og omgjøres til handlinger i et RDBMS. Det finnes to grunnleggende tilnærminger her:

**1. Kjør SQL-kode**interaktivt I denne metoden skrives eller kopieres SQL-koden direkte inn i et tekstvindu. SQL-koden kjøres, og resultatet vises. Du kan justere koden og kjøre den på nytt. Den raske vekslingen mellom å endre koden og vise resultatene gjør denne metoden best egnet for læring og utarbeidelse av komplekse spørsmål. **2. Kjør SQL-kode som**skript I denne tilnærmingen kjøres en hel kildekodefil som inneholder SQL-kode linje for linje. Om nødvendig sendes tilbakemelding til brukeren først ved slutten av kjøringen. Denne tilnærmingen er best egnet for automatisering av prosesser og for import av MySQL-databasesikkerhetskopier med MySQL dump.

<table>
  <thead>
    <tr>
      <th><strong>Grensesnitt</strong></th>
      <th><strong>Beskrivelse</strong></th>
      <th><strong>Eksempler</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Kommandolinjegrensesnitt (CLI)</td>
      <td>Tekstbasert grensesnitt; SQL-kode legges inn og kjøres, resultatet vises som tekst</td>
      <td>mysql, psql, mysqlsh</td>
    </tr>
    <tr>
      <td>Grafisk brukergrensesnitt (GUI)</td>
      <td>SQL-kode legges inn i et tekstvindu og/eller genereres som svar på brukerinteraksjon; SQL-koden kjøres, resultatet vises som tabeller</td>
      <td>phpMyAdmin, MySQL Workbench, HeidiSQL</td>
    </tr>
    <tr>
      <td>Programmeringsgrensesnitt (API)</td>
      <td>Muliggjør direkte kommunikasjon med et RDBMS; SQL-kode inkluderes og kjøres som en streng i koden til programmeringsspråket; resultatene er tilgjengelige som datastrukturer for videre bruk</td>
      <td>PHP Data Objects (PDO), Connector/J (Java), Connector/Python, C API</td>
    </tr>
  </tbody>
</table>

## Hvordan sette opp et produktstyringssystem ved hjelp av SQL

Den enkleste måten å lære et programmeringsspråk på er å skrive og kjøre koden selv. I denne veiledningen skal **vi lage en minidatabase og kjøre spørringer mot den**. Til dette bruker vi den [nettbaserte SQL-tolken](https://sql.js.org/examples/GUI/ "sql.js demo: Online SQL interpreter") fra nettstedet *sql.js*. For å følge veiledningen går du til nettstedet og erstatter SQL-koden som allerede er lagt inn, med koden fra eksemplene våre. Kjør koden bit for bit for å få resultatene vist.

### Opprett en SQL-database

I dette eksemplet skal vi utvikle et **produktstyringssystem** for en butikk. Dette er kravene:

- Vi har flere produkter, og vi har et visst antall av hvert produkt på lager.
- Vår kundebase består av mange kunder.
- Bestillinger fra kunder kan inneholde flere produkter.
- For hver bestilling lagrer vi bestillingsdatoen og opplysningene om personen som legger inn bestillingen, samt hvilke produkter som ble bestilt og bestillingsmengden.

Disse kravene oversettes til en **abstrakt beskrivelse og deretter til SQL-kode**:

1. Opprett modell
2. Definer skjema
3. Legg inn dataposter
4. Definer spørringer

### Opprett en modell av enheter og relasjoner

Det første trinnet foregår på papir eller ved hjelp av spesielle modelleringsverktøy. Vi samler inn informasjon om systemet som skal **modelleres for å utlede enheter og relasjoner**. Dette trinnet gjennomføres ofte i form av et entitet-relasjonsdiagram (ER-diagram).

Hvilke enheter finnes det, og hvordan henger de sammen? **Enheter er kategorier av objekter**. I eksemplet med produktstyringssystemet er enhetene produkter, kunder og bestillinger. For hver enhet trengs det en tabell. På grunn av relasjonsmodellens særtrekk må det legges til flere tabeller for å modellere relasjonene. Det krever erfaring å forstå dette og implementere det på riktig måte.

Et sentralt spørsmål som må besvares, er hvordan enhetene forholder seg til hverandre. Her må vi ta hensyn til **begge retningene i et forhold** og skille mellom **entall og flertall**. Her er et eksempel med biler og bileiere:

1. En eier kan potensielt eie flere biler.
2. En bil kan bare tilhøre én eier.

Det tegner seg**tre mulige relasjonsmønstre** mellom de to enhetene:

<table>
  <thead>
    <tr>
      <th><strong>Forhold</strong></th>
      <th><strong>Enheter</strong></th>
      <th><strong>Fra venstre</strong></th>
      <th><strong>Fra høyre</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1:1-relasjon</td>
      <td>Auto:indikator</td>
      <td>En bil kan bare ha én indikator.</td>
      <td>En indikator kan bare tilhøre én bil.</td>
    </tr>
    <tr>
      <td>1:n-relasjon</td>
      <td>Eier:bil</td>
      <td>En eier kan potensielt ha flere biler.</td>
      <td>En bil kan bare tilhøre én eier.</td>
    </tr>
    <tr>
      <td>m:n-relasjon</td>
      <td>Bil:gate</td>
      <td>En bil kan kjøre på flere veier.</td>
      <td>Flere biler kan kjøre på én vei.</td>
    </tr>
  </tbody>
</table>

### Implementere produkter

Først skal vi implementere produkttabellen. For å gjøre dette må vi definere et skjema, legge inn dataposter og, for testformål, kjøre noen enkle spørringer.

#### Definer skjema

Den viktigste SQL-kommandoen for å definere databasetabeller er CREATE TABLE. Denne kommandoen lar deg **opprette en tabell med et navn og angi kolonneegenskaper**. Samtidig defineres datatyper og, om nødvendig, begrensninger på verdiene som skal lagres:

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

Note Vi bruker en DROP TABLE IF EXISTS-setning før vi definerer tabellen. Dette fjerner eventuelle eksisterende tabeller og gjør det mulig å kjøre den samme SQL-koden flere ganger uten at det oppstår feilmeldinger.

#### Legg til datasett

Nå skal vi opprette noen **testposter**. Vi skal bruke SQL-kommandoen INSERT INTO samt VALUES-funksjonen til å fylle ut feltene:

```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);
```

#### Definer spørsmål

For **å sjekke tilstanden til tabellen «Products»** skal vi skrive en enkel spørring. Vi bruker kommandoen SELECT FROM og viser hele tabellen:

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

Nå skal vi skrive et litt mer komplisert spørsmål som beregner den **totale verdien av produktene vi har på lager**:

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

### Legg til flere tabeller

Nå skal vi **opprette de resterende tabellene vi trenger**. Vi følger de samme trinnene som vi brukte for tabellen «Produkter». Først oppretter vi tabellen «Kunder»:

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

Deretter legger vi inn opplysninger for to eksempler på kunder:

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

For å sjekke om det fungerte, skal vi vise kundetabellen:

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

Neste trinn er å opprette tabellen «Orders»:

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

Nå skal vi **legge inn tre eksempler på innkjøpsordrer**. For den første verdien i postene tildeler vi en ID som primærnøkkel. Den andre verdien er eksisterende kunde-ID-er, som fungerer som fremmednøkler. Deretter lagrer vi datoen for ordren:

```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');
```

For å teste det, skal vi utføre følgende kommandoer:

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

Til slutt trenger vi en tabell for **produktene i en ordre sammen med antallet av dem**. Dette er et m:n-forhold, fordi en ordre kan inneholde flere produkter, og et produkt kan forekomme i flere ordrer. Vi skal definere en tabell som inneholder ID-ene til ordrer og produkter som fremmednøkler:

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

Nå legger vi inn noen produkter som er bestilt. Vi velger ID-ene til bestillingene og produktene slik at det blir én bestilling med to produkter og en annen bestilling med bare ett produkt:

```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);
```

For å sjekke dette, skal vi sende ut de bestilte produktene:

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

### Skriv komplekse spørsmål

Hvis du har kjørt alle kodebitene som er vist så langt, bør du ha fått en god forståelse av strukturen i testdatabasen vår. La oss nå gå videre til mer komplekse spørringer som viser hvor kraftig SQL er. Først skal vi **skrive en spørring som slår sammen data spredt over flere tabeller**. Vi skal bruke en SQL JOIN-kommando for å koble sammen tabellene som inneholder kundedata og ordrer. Mens vi gjør dette, skal vi gi kolonnene navn og angi en samsvarende kunde-ID som JOIN-betingelse. Husk at vi bruker kvalifiserte identifikatorer for å skille mellom kolonnene i de to tabellene:

```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;
```

Nå skal vi bruke en ny JOIN-kommando for å beregne den **totale kostnaden for de bestilte produktene**:

```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;
```

Tip Vil du lære mer om [hva SQL er](https://www.ionos.com/nb-no/digitalguide/server/konfigurasjon/introduksjon-til-sql-med-eksempler/), eller trenger du hjelp til å løse et problem knyttet til databasespråket? Eller kanskje du bare ønsker å utvide kunnskapen din om SQL. Uansett hva som er tilfelle, finner du en rekke artikler om SQL og MySQL i vår digitale guide:

- MySQL-veiledning
- MariaDB vs. MySQL
- Hvordan installere og bruke MariaDB/MySQL
- Koble til en MySQL/MariaDB-database med PHP på en skyserver som kjører Linux
- Løs MySQL/MariaDB-feilen «Too many connections»
- Hvordan tilbakestille root-passordet for MySQL/MariaDB


This is a markdown version of: [https://www.ionos.com/nb-no/digitalguide/server/konfigurasjon/introduksjon-til-sql-med-eksempler/](https://www.ionos.com/nb-no/digitalguide/server/konfigurasjon/introduksjon-til-sql-med-eksempler/) for AI/LLM consumption.