# Lær SQL – En vejledning med kodeeksempler

SQL’s syntaks er baseret på **relationsalgebra**, hvilket adskiller dette programmeringssprog fra andre sprog. Ved at gøre dig fortrolig med syntaksen gennem praktiske eksempler kan du lære SQL på en effektiv måde.

## Hvad er SQL-syntaks?

I programmering henviser syntaks til **den måde, et programmeringssprog skrives på**. Syntaksen fastlægger de grundlæggende kodekonstruktioner og hvordan de skal sammenkædes. At forstå syntaksen er en grundlæggende forudsætning for at kunne læse og skrive kode i programmeringssprog.

De vigtigste syntakselementer i SQL er **SQL-sætninger, som også kan indeholde klausuler**. Begge betegnes ofte som »SQL-kommandoer«, selvom dette rent teknisk set ikke er helt korrekt. Det er dog ikke de eneste syntakselementer i SQL. Nedenfor finder du en tabel, der giver dig et overblik over syntakselementerne i SQL.

<table>
  <thead>
    <tr>
      <th><strong>SQL-udtryk</strong></th>
      <th><strong>Forklaring</strong></th>
      <th><strong>Eksempel</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Sætning</td>
      <td>Instruerer DBMS om at udføre en handling; slutter med et semikolon</td>
      <td>`CREATE TABLE People;`</td>
    </tr>
    <tr>
      <td>Klausul</td>
      <td>Modificerer en sætning; kan kun forekomme inden for sætninger</td>
      <td>`WHERE, HAVING`</td>
    </tr>
    <tr>
      <td>Udtryk</td>
      <td>Returnerer en værdi ved evaluering</td>
      <td>`6 * 7`</td>
    </tr>
    <tr>
      <td>Identifikator</td>
      <td>Navn på et databaseobjekt, en variabel eller en procedure; kan være kvalificeret eller ukvalificeret</td>
      <td>`dbname.tablename / tablename`</td>
    </tr>
    <tr>
      <td>Prædikat</td>
      <td>Udtryk, der evalueres til `TRUE, FALSE` eller `UNKNOWN`</td>
      <td>`Age < 42`</td>
    </tr>
    <tr>
      <td>Forespørgsel</td>
      <td>Speciel sætning; returnerer fundne sæt af poster</td>
      <td>`SELECT Name FROM People WHERE Age < 42;`</td>
    </tr>
    <tr>
      <td>Funktion</td>
      <td>Behandler en eller flere værdier; skaber normalt en ny værdi</td>
      <td>`UPPER('text') -- returns 'TEXT'`</td>
    </tr>
    <tr>
      <td>Kommentar</td>
      <td>Bruges til at kommentere SQL-kode; ignoreres af 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 normalt med store bogstaver. SQL skelner dog ikke mellem store og små bogstaver. Brugen af store bogstaver i kommandoerne er blot en udbredt konvention.

## Hvordan udføres SQL-kode?

SQL-kode findes som kildekode i tekstfiler. Koden kommer først til live i et passende kørselsmiljø. Kildekoden læses af en **SQL-fortolker** og omdannes til handlinger i et RDBMS. Der er to grundlæggende tilgange her:

**1. Udfør SQL-kode**interaktivt I denne fremgangsmåde indtastes eller kopieres SQL-koden direkte ind i et tekstvindue. SQL-koden udføres, og resultatet vises. Du kan justere koden og udføre den igen. Den hurtige afveksling mellem kodemanipulation og visning af resultater gør denne fremgangsmåde særdeles velegnet til at lære og oprette komplekse forespørgsler. **2. Udfør SQL-kode som**script I denne fremgangsmåde udføres en hel kildekodefil, der indeholder SQL-kode, linje for linje. Hvis det er nødvendigt, sendes feedback kun til brugeren ved afslutningen af udførelsen. Denne fremgangsmåde er bedst egnet til automatisering af processer og til import af MySQL-database-backups med MySQL dump.

<table>
  <thead>
    <tr>
      <th><strong>Grænseflade</strong></th>
      <th><strong>Beskrivelse</strong></th>
      <th><strong>Eksempler</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Kommandolinjegrænseflade (CLI)</td>
      <td>Tekstbaseret grænseflade; SQL-kode indtastes og udføres, resultatet vises som tekst</td>
      <td>mysql, psql, mysqlsh</td>
    </tr>
    <tr>
      <td>Grafisk brugergrænseflade (GUI)</td>
      <td>SQL-kode indtastes i et tekstvindue og/eller genereres som reaktion på brugerinteraktion; SQL-kode udføres, resultatet vises som tabeller</td>
      <td>phpMyAdmin, MySQL Workbench, HeidiSQL</td>
    </tr>
    <tr>
      <td>Applikationsprogrammeringsgrænseflade (API)</td>
      <td>Muliggør direkte kommunikation med et RDBMS; SQL-kode indgår og udføres som en streng i programmeringssprogets kode; resultaterne er tilgængelige som datastrukturer til videre brug</td>
      <td>PHP Data Objects (PDO), Connector/J (Java), Connector/Python, C API</td>
    </tr>
  </tbody>
</table>

## Sådan opretter du et produktstyringssystem ved hjælp af SQL

Den nemmeste måde at lære et programmeringssprog på er at skrive og køre koden selv. I denne vejledning skal vi **oprette en minidatabase og køre forespørgsler på den**. Til det formål bruger vi [online-SQL-fortolkeren](https://sql.js.org/examples/GUI/ "sql.js demo: Online SQL interpreter") fra hjemmesiden *sql.js*. For at følge vejledningen skal du gå ind på hjemmesiden og erstatte den SQL-kode, der allerede er indtastet, med koden fra vores eksempler. Kør koden stykke for stykke for at få resultaterne vist.

### Opret en SQL-database

I dette eksempel skal vi udvikle et **produktstyringssystem** til en butik. Her er kravene:

- Vi har flere forskellige produkter, og vi har et bestemt antal af hvert produkt på lager.
- Vores kundebase omfatter mange kunder.
- Ordrer afgivet af kunder kan indeholde flere produkter.
- For hver ordre gemmer vi ordredatoen og oplysninger om den person, der har afgivet ordren, samt de bestilte produkter og den bestilte mængde.

Disse krav omsættes først til en **abstrakt beskrivelse og derefter til SQL-kode**:

1. Opret model
2. Definer skema
3. Indtast dataposter
4. Definer forespørgsler

### Opret en model over enheder og relationer

Det første trin foregår på papir eller ved hjælp af specielle modelleringsværktøjer. Vi indsamler oplysninger om det system, der skal **modelleres, for at udlede enheder og relationer**. Dette trin udmøntes ofte i et entitet-relationsdiagram (ER-diagram).

Hvilke enheder findes der, og hvordan hænger de sammen? **Enheder er kategorier af objekter**. I vores eksempel på et produktstyringssystem er enhederne produkter, kunder og ordrer. Der skal oprettes en tabel for hver enhed. På grund af den relationelle models særlige karakteristika tilføjes der yderligere tabeller for at modellere sammenhængene. Det kræver erfaring at forstå dette og implementere det korrekt.

Et centralt spørgsmål, der skal besvares, er, hvordan enhederne forholder sig til hinanden. Her skal vi tage højde for **begge retninger i en relation** og skelne mellem **ental og flertal**. Her er et eksempel med biler og bilejere:

1. En ejer kan potentielt eje flere biler.
2. En bil kan kun tilhøre én ejer.

Der tegner sig**tre mulige mønstre for forholdet** mellem de to enheder:

<table>
  <thead>
    <tr>
      <th><strong>Forhold</strong></th>
      <th><strong>Enheder</strong></th>
      <th><strong>Fra venstre</strong></th>
      <th><strong>Fra højre</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1:1-relation</td>
      <td>Auto:indikator</td>
      <td>En bil kan kun have én indikator.</td>
      <td>En indikator kan kun tilhøre én bil.</td>
    </tr>
    <tr>
      <td>1:n-relation</td>
      <td>Ejer:bil</td>
      <td>En ejer kan potentielt have flere biler.</td>
      <td>En bil kan kun tilhøre én ejer.</td>
    </tr>
    <tr>
      <td>m:n-relation</td>
      <td>Bil:gade</td>
      <td>En bil kan køre på flere veje.</td>
      <td>Flere biler kan køre på én vej.</td>
    </tr>
  </tbody>
</table>

### Implementere produkter

Først skal vi oprette produkttabellen. For at gøre dette skal vi definere et skema, indtaste dataposter og, med henblik på test, køre et par enkle forespørgsler.

#### Definer skema

Den centrale SQL-kommando til oprettelse af databasetabeller er CREATE TABLE. Med denne kommando kan du **oprette en tabel med et navn og angive kolonneegenskaber**. Samtidig defineres datatyper og, hvis nødvendigt, begrænsninger for de værdier, der skal gemmes:

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

Note Vi bruger en DROP TABLE IF EXISTS-sætning, før vi definerer tabellen. Dette sletter eventuelle eksisterende tabeller og gør det muligt at køre den samme SQL-kode flere gange uden at der vises fejlmeddelelser.

#### Tilføj datasæt

Nu skal vi oprette et par **testposter**. Vi bruger SQL-kommandoen INSERT INTO samt funktionen VALUES til at udfylde felterne:

```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 forespørgsler

For **at se, hvordan det står til med tabellen »Produkter«**, skriver vi en simpel forespørgsel. Vi bruger kommandoen SELECT FROM og viser hele tabellen:

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

Nu skal vi skrive en lidt mere kompleks forespørgsel, der beregner den **samlede værdi af de varer, vi har på lager**:

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

### Opret yderligere tabeller

Nu skal vi **oprette de resterende tabeller, vi har brug for**. Vi følger de samme trin, som vi brugte til tabellen »Produkter«. Først opretter vi tabellen »Kunder«:

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

Derefter indtaster vi data 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 at se, om det virkede, viser vi kundetabellen:

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

Det næste trin er at oprette tabellen »Orders«:

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

Nu skal vi **indtaste tre eksempler på indkøbsordrer**. For den første værdi i posterne tildeler vi et ID som primærnøgle. Den anden værdi er eksisterende kunde-ID’er, som fungerer som fremmednøgler. Derefter gemmer vi ordredatoen:

```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 at teste det vil vi udføre følgende kommandoer:

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

Endelig har vi brug for en tabel, der indeholder **produkterne i en ordre sammen med deres antal**. Dette er et m:n-forhold, da en ordre kan indeholde flere produkter, og et produkt kan forekomme i flere ordrer. Vi opretter en tabel, der indeholder ID’erne for ordrer og produkter som fremmednøgler:

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

Nu indtaster vi et par produkter, der er blevet bestilt. Vi vælger ID’erne for ordrerne og produkterne, så der er en ordre med to produkter og en anden ordre med kun ét 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 at kontrollere dette vil vi udlevere de bestilte varer:

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

### Skriv komplekse forespørgsler

Hvis du har kørt alle de kodestykker, der er vist indtil nu, bør du kunne forstå strukturen i vores testdatabase. Lad os nu gå videre til mere komplekse forespørgsler, der viser, hvor kraftfuldt SQL er. Lad os først **skrive en forespørgsel, der samler data fra flere forskellige tabeller**. Vi bruger en SQL JOIN-kommando til at sammenføje de tabeller, der indeholder kundedata og ordrer. I den forbindelse navngiver vi kolonnerne og angiver et matchende kunde-ID som JOIN-betingelse. Husk, at vi bruger kvalificerede identifikatorer til at skelne mellem kolonnerne i de to tabeller:

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

Nu bruger vi endnu en JOIN-kommando til at beregne de **samlede omkostninger for de bestilte produkter**:

```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 vide mere om, [hvad SQL er](https://www.ionos.com/da-dk/digitalguide/server/konfiguration/introduktion-til-sql-med-eksempler/), eller har du brug for hjælp til at løse et problem med databasesproget? Eller måske vil du bare udvide din viden om SQL. Uanset hvad, kan du finde en række artikler om SQL og MySQL i vores digitale guide:

- MySQL-vejledning
- MariaDB vs. MySQL
- Sådan installeres og bruges MariaDB/MySQL
- Opret forbindelse til en MySQL/MariaDB-database med PHP på en cloud-server, der kører Linux
- Løs MySQL/MariaDB-fejlen “For mange forbindelser”
- Sådan nulstilles root-adgangskoden til MySQL/MariaDB


This is a markdown version of: [https://www.ionos.com/da-dk/digitalguide/server/konfiguration/introduktion-til-sql-med-eksempler/](https://www.ionos.com/da-dk/digitalguide/server/konfiguration/introduktion-til-sql-med-eksempler/) for AI/LLM consumption.