SQL leren – Een tutorial met codevoorbeelden
De syntaxis van SQL is gebaseerd op relationele algebra, waardoor deze programmeertaal verschilt van andere talen. Door uzelf vertrouwd te maken met de syntaxis aan de hand van praktische voorbeelden, kunt u SQL effectief leren.
Wat is SQL-syntaxis?
In de programmering verwijst syntaxis naar de manier waarop een programmeertaal wordt geschreven. De syntaxis bepaalt de basisconstructies van de code en hoe deze met elkaar worden verbonden. Inzicht in de syntaxis is een fundamentele vereiste voor het lezen en schrijven van code in programmeertalen.
De belangrijkste syntaxisconstructies in SQL zijn SQL-statements, die ook clausules kunnen bevatten. Beide worden gewoonlijk ‘SQL-commando’s’ genoemd, hoewel dit vanuit technisch oogpunt niet helemaal correct is. Dit zijn echter niet de enige SQL-syntaxisconstructies. Hieronder vindt u een tabel met een overzicht van de SQL-syntaxisconstructies.
| SQL-term | Uitleg | Voorbeeld |
|---|---|---|
| Statement | Geeft het DBMS opdracht om een actie uit te voeren; eindigt met een puntkomma | CREATE TABLE People;
|
| Clausule | Wijzigt een instructie; kan alleen binnen instructies voorkomen | WHERE, HAVING
|
| Expressie | Geeft een waarde terug bij evaluatie | 6 * 7
|
| Identificatie | Naam van een databaseobject, variabele of procedure; kan gekwalificeerd of ongekwalificeerd zijn. | dbname.tablename / tablename
|
| Predikaat | Uitdrukking die wordt geëvalueerd tot TRUE, FALSE of UNKNOWN
|
Age < 42
|
| Query | Speciale instructie; retourneert gevonden set records | SELECT Name FROM People WHERE Age < 42;
|
| Functie | Verwerkt een of meer waarden; creëert meestal een nieuwe waarde | UPPER('text') -- returns 'TEXT'
|
| Commentaar | Wordt gebruikt om SQL-code te becommentariëren; wordt genegeerd door het RDBMS | -- Comment up to end of line / /*multiline comment if necessary*/
|
SQL-opdrachten zoals SELECT en CREATE TABLE worden meestal met hoofdletters geschreven. SQL is echter niet hoofdlettergevoelig. Het gebruik van hoofdletters voor opdrachten is slechts een veelgebruikte conventie.
Hoe wordt SQL-code uitgevoerd?
SQL-code bestaat als broncode in tekstbestanden. De code komt alleen tot leven in een geschikte uitvoeringsomgeving. De broncode wordt gelezen door een SQL-interpreter en omgezet in acties van een RDBMS. Hierbij zijn er twee basisbenaderingen:
1. SQL-code interactief uitvoerenBij deze aanpak wordt SQL-code rechtstreeks in een tekstvenster ingevoerd of gekopieerd. De SQL-code wordt uitgevoerd en het resultaat wordt weergegeven. U kunt de code aanpassen en opnieuw uitvoeren. Door de snelle opeenvolging van codemanipulatie en weergave van resultaten is deze aanpak het meest geschikt voor het leren en maken van complexe query’s. 2. SQL-code als script uitvoerenBij deze aanpak wordt een volledig broncodebestand met SQL-code regel voor regel uitgevoerd. Indien nodig wordt er pas aan het einde van de uitvoering feedback naar de gebruiker gestuurd. Deze aanpak is het meest geschikt voor het automatiseren van processen en voor het importeren van MySQL-databaseback-ups met MySQL dump.
| Interface | Beschrijving | Voorbeelden |
|---|---|---|
| Opdrachtregelinterface (CLI) | Tekstgebaseerde interface; SQL-code wordt ingevoerd en uitgevoerd, resultaat wordt weergegeven in tekst | mysql, psql, mysqlsh |
| Grafische gebruikersinterface (GUI) | SQL-code wordt ingevoerd in een tekstvenster en/of gegenereerd als reactie op interactie van de gebruiker; SQL-code wordt uitgevoerd, resultaat wordt weergegeven in tabellen | phpMyAdmin, MySQL Workbench, HeidiSQL |
| Application Programming Interface (API) | Maakt directe communicatie met een RDBMS mogelijk; SQL-code wordt opgenomen en uitgevoerd als een tekenreeks in de code van de programmeertaal; resultaten zijn beschikbaar als gegevensstructuren voor verder gebruik | PHP Data Objects (PDO), Connector/J (Java), Connector/Python, C API |
Hoe een productbeheersysteem opzetten met behulp van SQL
De eenvoudigste manier om een programmeertaal te leren, is door zelf code te schrijven en uit te voeren. In deze tutorial maken we een minidatabase en voeren we daar query’s op uit. Hiervoor gebruiken we de online SQL-interpreter van de website sql.js. Om de tutorial te volgen, ga je naar de website en vervang je de reeds ingevoerde SQL-code door de code uit onze voorbeelden. Voer de code stukje voor stukje uit om de resultaten weer te geven.
Een SQL-database opzetten
In dit voorbeeld gaan we een commercieel productbeheersysteem voor een winkel bouwen. Dit zijn de vereisten:
- Er zijn verschillende producten en we hebben van elk product een bepaalde hoeveelheid op voorraad.
- Ons klantenbestand omvat veel klanten en afnemers.
- Bestellingen van klanten kunnen meerdere producten bevatten.
- Voor elke bestelling slaan we de besteldatum en de gegevens van de persoon die de bestelling heeft geplaatst op, evenals de bestelde producten en de bestelde hoeveelheid.
Deze vereisten worden vertaald naar een abstracte beschrijving en vervolgens naar SQL-code:
- Model maken
- Schema definiëren
- Gegevensrecords invoeren
- Query’s definiëren
Maak een model van entiteiten en relaties
De eerste stap vindt plaats op papier of met speciale modelleertools. We verzamelen informatie over het te modelleren systeem om entiteiten en relaties af te leiden. Deze stap wordt vaak gerealiseerd als een Entity Relationship (ER)-diagram.
Welke entiteiten zijn er en hoe zijn ze met elkaar verbonden? Entiteiten zijn categorieën van dingen. In ons voorbeeld van het productbeheersysteem zijn de entiteiten producten, klanten en bestellingen. Voor elke entiteit is een tabel nodig. Vanwege de specifieke kenmerken van het relationele model worden er extra tabellen toegevoegd om de relaties te modelleren. Om dit te herkennen en correct te implementeren, is ervaring nodig.
Een centrale vraag die beantwoord moet worden, is hoe de entiteiten zich tot elkaar verhouden. Hierbij moeten we beide richtingen van een relatie in ogenschouw nemen en onderscheid maken tussen enkelvoud en meervoud. Hier volgt een voorbeeld met auto’s en autobezitters:
- Eén eigenaar kan mogelijk meerdere auto’s bezitten.
- Een auto kan slechts aan één eigenaar toebehoren.
Er zijndrie mogelijke relatiepatronen tussen de twee entiteiten:
| Relatie | Entiteiten | Van links | Van rechts |
|---|---|---|---|
| 1:1-relatie | Auto:indicator | Een auto kan slechts één richtingaanwijzer hebben. | Een richtingaanwijzer kan slechts bij één auto horen. |
| 1:n-relatie | Eigenaar:auto | Een eigenaar kan mogelijk meerdere auto’s hebben. | Een auto kan slechts bij één eigenaar horen. |
| m:n-relatie | Auto:straat | Een auto kan op meerdere wegen rijden. | Meerdere auto’s kunnen op één weg rijden. |
Producten implementeren
Eerst implementeren we de productentabel. Hiervoor moeten we een schema definiëren, gegevensrecords invoeren en, voor testdoeleinden, een paar eenvoudige query’s uitvoeren.
Schema definiëren
Het centrale SQL-commando voor het definiëren van databasetabellen is CREATE TABLE. Met dit commando kunt u een tabel met een naam aanmaken en kolomeigenschappen specificeren. Tegelijkertijd worden gegevenstypen en, indien nodig, beperkingen op de op te slaan waarden gedefinieerd:
DROP TABLE IF EXISTS Products;
CREATE TABLE Products ( product_id int, product_name text, stocked int, price int );sqlWe gebruiken een DROP TABLE IF EXISTS-instructie voordat we de tabel definiëren. Hierdoor wordt elke bestaande tabel verwijderd en kan dezelfde SQL-code meerdere keren worden uitgevoerd zonder dat er foutmeldingen worden gegenereerd.
Dataset toevoegen
Nu gaan we een paar testrecords aanmaken. We gebruiken het SQL-commando INSERT INTO en de functie VALUES om de velden in te vullen:
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);sqlQueries definiëren
Om de status van de tabel Products te controleren, schrijven we een eenvoudige query. We gebruiken het commando SELECT FROM en geven de volledige tabel weer:
SELECT * FROM Products;sqlNu gaan we een iets complexere query schrijven die de totale waarde berekent van de producten die we op voorraad hebben:
SELECT product_name AS 'Name', (stocked * price) AS 'Value' FROM Products;sqlExtra tabellen implementeren
Vervolgens maken we de resterende tabellen die we nodig hebben. We volgen dezelfde stappen als voor de tabel Producten. Eerst maken we de tabel Klanten:
DROP TABLE IF EXISTS Customers;
CREATE TABLE Customers ( customer_id int, customer_name text, contact text );sqlVervolgens voeren we gegevensrecords in voor twee voorbeeldklanten:
INSERT INTO Customers VALUES (100, 'EDC Customer', 'ED@example.com');
INSERT INTO Customers VALUES (200, 'WVU Customer', 'WV@example.com');sqlOm te controleren of het gewerkt heeft, geven we de klantentabel weer:
SELECT * FROM Customers;sqlDe volgende stap is het aanmaken van de tabel Orders:
DROP TABLE IF EXISTS Orders;
CREATE TABLE Orders ( order_id int, customer_id int, order_date text );sqlNu voeren we drie voorbeeldinkooporders in. Voor de eerste waarde van de records wijzen we een ID toe als primaire sleutel. De tweede waarde is voor bestaande klant-ID’s, die fungeren als externe sleutels. Vervolgens slaan we de datum van de bestelling op:
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');sqlOm dit te testen, geven we de volgende opdrachten:
SELECT * FROM Orders;sqlTen slotte hebben we een tabel nodig voor de producten in een bestelling, samen met hun hoeveelheid. Dit is een m:n-relatie, omdat een bestelling meerdere producten kan bevatten en een product in meerdere bestellingen kan voorkomen. We definiëren een tabel die de ID’s van bestellingen en producten als externe sleutels bevat:
DROP TABLE IF EXISTS OrderItems;
CREATE TABLE OrderItems ( orderitem_id int, order_id int, product_id int, count int );sqlNu voeren we een aantal bestelde producten in. We kiezen de ID’s van de bestellingen en producten zo dat er een bestelling is met twee producten en een andere bestelling met slechts één product:
INSERT INTO OrderItems VALUES (10001, 1000, 10, 3);
INSERT INTO OrderItems VALUES (10002, 1000, 20, 2);
INSERT INTO OrderItems VALUES (10003, 1002, 30, 12);sqlOm dit te controleren, zullen we de bestelde producten verzenden:
SELECT * FROM OrderItems;sqlSchrijf complexe query’s
Als u alle tot nu toe getoonde codefragmenten hebt uitgevoerd, zou u de structuur van onze testdatabase moeten begrijpen. Laten we nu verdergaan met complexere query’s die de kracht van SQL demonstreren. Laten we eerst een query schrijven die gegevens uit meerdere tabellen samenvoegt. We gebruiken een SQL JOIN-opdracht om de tabellen met klantgegevens en bestellingen samen te voegen. Daarbij geven we de kolommen een naam en stellen we een overeenkomende klant-ID in als JOIN-voorwaarde. Houd er rekening mee dat we gekwalificeerde identificatiecodes gebruiken om onderscheid te maken tussen de kolommen van de twee tabellen:
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;sqlNu gebruiken we nog een JOIN-commando om de totale kosten van de bestelde producten te berekenen:
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;sql