Waarom geschiedenis bewaren
Auditing, terugdraaien en analyses van het verleden
Waarom geschiedenis bewaren is een gratis SQL Academy-les op CoddyKit. Dit is les 1 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject SQL Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus SQL Academy bevat in totaal 4 lessen.
Het probleem met overschrijven
Elke keer dat je UPDATE of DELETE uitvoert, verdwijnen de oude gegevens voorgoed. Dat klinkt efficiënt, maar het veroorzaakt echte problemen: je kunt geen vragen beantwoorden zoals wat was de prijs afgelopen dinsdag? of wie heeft deze rij gewijzigd en wanneer?
Geschiedenis bijhouden betekent dat je elke versie van een rij opslaat, niet alleen de nieuwste. In deze les ontdek je waarom dat belangrijk is en hoe SQL je daarbij helpt.
Drie redenen om geschiedenis te bewaren
Er zijn drie klassieke redenen om historische gegevens in een database te bewaren:
1. Controle — aantonen dat een wijziging heeft plaatsgevonden, wie die heeft aangebracht en wanneer.
2. Ongedaan maken — een fout terugdraaien zonder de hele database te herstellen.
3. Analyse — vragen over het verleden beantwoorden, trends herkennen en perioden vergelijken.
Een goed ontworpen strategie voor het bewaren van geschiedenis voorziet in alle drie de behoeften zonder al te veel opslag te dupliceren.
Een eenvoudige controletabel
De eenvoudigste aanpak is een aparte controletabel waarin elke wijziging wordt vastgelegd. Elke rij bevat de oude waarde, de nieuwe waarde, wie de wijziging heeft aangebracht en wanneer.
Hieronder staat een controletabel voor een tabel products. De kolom operation bevat INSERT, UPDATE of DELETE.
CREATE TABLE products_audit (
audit_id SERIAL PRIMARY KEY,
product_id INT NOT NULL,
operation VARCHAR(6) NOT NULL, -- INSERT / UPDATE / DELETE
old_price NUMERIC(10,2),
new_price NUMERIC(10,2),
changed_by TEXT NOT NULL,
changed_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);De controletabel vullen
Je kunt handmatig naar een controletabel schrijven, maar de betrouwbaarste aanpak is een databasetrigger die automatisch wordt geactiveerd wanneer gegevens veranderen. Zo kan geen enkele applicatiecode het logboek omzeilen.
Hier voegen we rechtstreeks één controleregel toe om de structuur te laten zien voordat we triggers behandelen.
INSERT INTO products_audit (product_id, operation, old_price, new_price, changed_by)
VALUES (42, 'UPDATE', 9.99, 12.49, 'alice');
SELECT * FROM products_audit ORDER BY changed_at DESC LIMIT 5;Het controlelogboek lezen
Zodra zich rijen in de controletabel opstapelen, kun je ze opvragen om controlevragen te beantwoorden. De onderstaande query toont de volledige prijsgeschiedenis van één product, met de recentste wijziging eerst.
SELECT
changed_at,
changed_by,
operation,
old_price,
new_price
FROM products_audit
WHERE product_id = 42
ORDER BY changed_at DESC;Geldigheidsdatums: geschiedenis op basis van geldigheid
Een controletabel registreert wanneer je de wijziging hebt aangebracht (transactietijd). Soms moet je ook bijhouden wanneer iets in de echte wereld waar was — dit heet geldigheidstijd.
Door de kolommen valid_from en valid_to aan de hoofdtabel toe te voegen, maak je een geschiedenis op basis van geldigheid, ook wel een langzaam veranderende dimensie genoemd (SCD Type 2).
CREATE TABLE employee_history (
id SERIAL PRIMARY KEY,
employee_id INT NOT NULL,
department TEXT NOT NULL,
salary NUMERIC(10,2) NOT NULL,
valid_from DATE NOT NULL,
valid_to DATE -- NULL means current record
);
-- Current record for employee 7
INSERT INTO employee_history (employee_id, department, salary, valid_from)
VALUES (7, 'Engineering', 85000, '2023-01-01');Een langzaam veranderende rij bijwerken
Wanneer een medewerker van afdeling verandert, werk je diens rij niet bij. In plaats daarvan sluit je de oude rij door valid_to in te stellen en voeg je een nieuwe rij zonder einddatum toe. Zo blijft de volledige geschiedenis behouden.
-- Step 1: close the current record
UPDATE employee_history
SET valid_to = '2024-06-01'
WHERE employee_id = 7 AND valid_to IS NULL;
-- Step 2: insert the new record
INSERT INTO employee_history (employee_id, department, salary, valid_from)
VALUES (7, 'Product', 90000, '2024-06-01');
-- Verify history
SELECT department, salary, valid_from, valid_to
FROM employee_history
WHERE employee_id = 7
ORDER BY valid_from;Een moment in de tijd opvragen
Met kolommen voor geldigheid kun je vragen wat op een bepaalde datum waar was — een query die met een model waarin je gewone UPDATE's gebruikt onmogelijk zou zijn.
De WHERE-clausule controleert of de doeldatum binnen het geldigheidsinterval van de rij valt.
-- What department and salary did employee 7 have on 2023-09-15?
SELECT department, salary, valid_from, valid_to
FROM employee_history
WHERE employee_id = 7
AND valid_from <= '2023-09-15'
AND (valid_to > '2023-09-15' OR valid_to IS NULL);Temporele tabellen met systeemversies
Moderne SQL-databases (PostgreSQL 16+, SQL Server, MySQL 8) ondersteunen temporele tabellen met systeemversies. De database houdt de transactietijd automatisch bij in verborgen kolommen en je kunt eerdere toestanden opvragen met een speciale syntaxis.
Voorbeeld voor SQL Server — het concept is voor alle databasesystemen hetzelfde:
-- SQL Server / MariaDB style (illustrative)
CREATE TABLE orders (
order_id INT PRIMARY KEY,
status VARCHAR(20),
total NUMERIC(10,2),
SysStartTime DATETIME2 GENERATED ALWAYS AS ROW START,
SysEndTime DATETIME2 GENERATED ALWAYS AS ROW END,
PERIOD FOR SYSTEM_TIME (SysStartTime, SysEndTime)
) WITH (SYSTEM_VERSIONING = ON);
-- Query historical state
SELECT * FROM orders FOR SYSTEM_TIME AS OF '2024-01-15 12:00:00'
WHERE order_id = 100;Geschiedenis gebruiken om ongedaan te maken
Historietabellen zijn niet alleen bedoeld om te lezen — je kunt ze ook gebruiken om fouten ongedaan te maken. Als een batchtaak 500 prijsrecords heeft beschadigd, kun je die vanuit de audit-tabel herstellen zonder een reservekopie aan te raken.
-- Undo all price changes made by the bad batch job at a specific time
UPDATE products p
SET price = a.old_price
FROM products_audit a
WHERE p.id = a.product_id
AND a.operation = 'UPDATE'
AND a.changed_by = 'batch_job'
AND a.changed_at BETWEEN '2024-03-10 02:00:00' AND '2024-03-10 02:05:00';
-- Confirm affected rows
SELECT COUNT(*) AS rows_restored FROM products_audit
WHERE changed_by = 'batch_job'
AND changed_at BETWEEN '2024-03-10 02:00:00' AND '2024-03-10 02:05:00';Analyses door de tijd heen
Historische gegevens maken tijdreeksanalyses mogelijk. Je kunt volgen hoe een metriek zich heeft ontwikkeld, cijfers van opeenvolgende maanden vergelijken of afwijkingen detecteren — allemaal zonder een afzonderlijk datawarehouse te gebruiken.
Deze query toont de gemiddelde prijs van een product per kalendermaand met behulp van de audit-tabel.
SELECT
DATE_TRUNC('month', changed_at) AS month,
ROUND(AVG(new_price), 2) AS avg_price
FROM products_audit
WHERE product_id = 42
AND operation IN ('INSERT', 'UPDATE')
GROUP BY 1
ORDER BY 1;Kennistoets
Test je kennis van historische gegevensopslag in SQL.
Samenvatting: waarom geschiedenis bewaren
In deze les heb je geleerd waarom het overschrijven van gegevens riskant is en hoe SQL-patronen de geschiedenis bewaren voor controle, ongedaan maken en analyses.
Belangrijkste punten:
- Audit-tabellen registreren elke INSERT, UPDATE en DELETE, met wie dit deed en wanneer.
- Rijen met geldigheidstijd (SCD Type 2) gebruiken de kolommen
valid_fromenvalid_toom tijdlijnen uit de echte wereld vast te leggen. - Query's voor een bepaald moment beantwoorden historische vragen door op die datumkolommen te filteren.
- Systeemgeversioneerde temporele tabellen automatiseren het bijhouden van transactietijd op databaseniveau.
- Historische gegevens maken gericht ongedaan maken en uitgebreide tijdreeksanalyses mogelijk, zonder reservekopieën nodig te hebben.
Het verleden bewaren is geen overhead — het is de basis voor betrouwbare systemen waarvan je de werking kunt controleren.
Leer SQL met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 46
- Lessen
- 183
Veelgestelde vragen
Is de les “Waarom geschiedenis bewaren” gratis?
Ja — de volledige tekst van “Waarom geschiedenis bewaren” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus SQL Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus SQL Academy bevat in totaal 4 lessen.
Wat leer ik in “Waarom geschiedenis bewaren”?
Auditing, terugdraaien en analyses van het verleden Je oefent met SQL Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met SQL Academy te beginnen?
Ervaring vooraf is niet nodig. SQL Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 1 van 4.
Hoe lang duurt de les “Waarom geschiedenis bewaren”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over SQL Academy?
Ja. Elke les over SQL Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Waarom geschiedenis bewaren
- Eventtabellen met alleen toevoegingen
- Tijdelijke en versiebeheerste rijen
- Status opnieuw opbouwen uit events