Tijdelijke en versiebeheerste rijen
Query's op geldige tijd en op een bepaald tijdstip
Tijdelijke en versiebeheerste rijen is een gratis SQL Academy-les op CoddyKit. Dit is les 3 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.
Wat zijn temporele tabellen?
Met temporele tabellen kun je volgen hoe gegevens in de loop van de tijd veranderen. In plaats van een rij bij een wijziging te overschrijven, bewaart een temporele tabel elke versie van die rij, voorzien van de periode waarin die versie geldig was.
Er zijn twee belangrijke concepten: geldigheidstijd (wanneer het feit in de echte wereld waar was) en transactietijd (wanneer de database het feit heeft vastgelegd). Door beide te combineren, krijg je een volledig bitemporele tabel.
Geldigheidstijd versus transactietijd
Geldigheidstijd geeft aan wanneer een feit in de echte wereld waar is — bijvoorbeeld het salaris van een werknemer van 2020-01-01 tot 2022-06-30. Transactietijd is het moment waarop de database de rij invoegde of ongeldig verklaarde. Samen beantwoorden ze twee vragen: Wat was waar? en Wanneer wisten we dat?
De meeste praktische toepassingen beginnen met het bijhouden van geldigheidstijd. Dat kun je handmatig implementeren met de kolommen valid_from en valid_to.
Een tabel met geldigheidstijd maken
De eenvoudigste manier om versiebeheerste rijen op te slaan, is het toevoegen van tijdstempelkolommen valid_from en valid_to. Een waarde NULL voor valid_to (of een speciale verre-toekomstwaarde zoals 9999-12-31) betekent dat de rij momenteel actief is.
CREATE TABLE employee_salary (
id SERIAL PRIMARY KEY,
employee_id INT NOT NULL,
salary NUMERIC(12, 2) NOT NULL,
valid_from DATE NOT NULL,
valid_to DATE
);
INSERT INTO employee_salary (employee_id, salary, valid_from, valid_to)
VALUES
(1, 50000, '2020-01-01', '2022-06-30'),
(1, 60000, '2022-07-01', NULL);De huidige versie opvragen
Om de momenteel actieve rij voor elke werknemer te vinden, filter je op rijen waarvoor valid_to IS NULL geldt (zonder einddatum), of waarop de datum van vandaag binnen het geldigheidsbereik valt. Een speciale waarde zoals '9999-12-31' maakt vergelijkingen van bereiken eenvoudiger.
SELECT employee_id, salary
FROM employee_salary
WHERE valid_to IS NULL
ORDER BY employee_id;Query's voor een bepaald moment
Een query voor een bepaald moment vraagt: Hoe zagen de gegevens er op een specifiek moment uit? Je filtert op rijen waarvan de opgegeven tijdstempel binnen de geldigheidsperiode valt. Dit is een van de krachtigste functies van temporele tabellen.
-- What was employee 1's salary on 2021-03-15?
SELECT employee_id, salary, valid_from, valid_to
FROM employee_salary
WHERE employee_id = 1
AND valid_from <= '2021-03-15'
AND (valid_to IS NULL OR valid_to > '2021-03-15');Een versiebeheerste rij bijwerken
Wanneer een feit verandert, voer je niet rechtstreeks een UPDATE uit op de bestaande rij. In plaats daarvan sluit je de huidige rij door de waarde van valid_to in te stellen en voeg je een nieuwe rij met de nieuwe waarde in met INSERT. Zo blijft de volledige geschiedenis behouden.
-- Employee 1 gets a raise effective 2023-01-01
BEGIN;
-- Close the current open row
UPDATE employee_salary
SET valid_to = '2022-12-31'
WHERE employee_id = 1
AND valid_to IS NULL;
-- Insert the new version
INSERT INTO employee_salary (employee_id, salary, valid_from, valid_to)
VALUES (1, 72000, '2023-01-01', NULL);
COMMIT;daterange gebruiken voor geldigheidsperioden
Het PostgreSQL-type daterange modelleert een geldigheidsperiode op elegante wijze in één kolom. Je kunt de operator @> (bevat) gebruiken om te controleren of een datum binnen het bereik valt en een uitsluitingsbeperking toevoegen om overlappende perioden voor dezelfde entiteit te voorkomen.
CREATE TABLE employee_salary_v2 (
id SERIAL PRIMARY KEY,
employee_id INT NOT NULL,
salary NUMERIC(12, 2) NOT NULL,
valid_period DATERANGE NOT NULL,
EXCLUDE USING GIST (employee_id WITH =, valid_period WITH &&)
);
INSERT INTO employee_salary_v2 (employee_id, salary, valid_period)
VALUES
(1, 50000, '[2020-01-01, 2022-07-01)'),
(1, 60000, '[2022-07-01, infinity)');Query voor een bepaald moment met daterange
Met de aanpak op basis van daterange wordt de query voor een bepaald moment zeer leesbaar. De operator @> controleert of de opgegeven datum binnen het bereik valt en verwerkt de onder- en bovengrens automatisch.
-- What was employee 1's salary on 2021-03-15?
SELECT employee_id, salary, valid_period
FROM employee_salary_v2
WHERE employee_id = 1
AND valid_period @> '2021-03-15'::date;Door het systeem geversioneerde tabellen (SQL-standaard)
De SQL:2011-standaard introduceerde systeemgeversioneerde temporele tabellen. De database beheert automatisch de transactietijdkolommen row_start en row_end. In PostgreSQL boots je dit na; in SQL Server en MariaDB is het ingebouwd met SYSTEM VERSIONING.
Het onderstaande voorbeeld toont de syntaxis van SQL Server en MariaDB als verwijzing naar het concept.
-- SQL Server / MariaDB syntax (reference)
CREATE TABLE dbo.Product (
ProductID INT PRIMARY KEY,
Name VARCHAR(100),
Price DECIMAL(10,2),
SysStart DATETIME2 GENERATED ALWAYS AS ROW START,
SysEnd DATETIME2 GENERATED ALWAYS AS ROW END,
PERIOD FOR SYSTEM_TIME (SysStart, SysEnd)
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.Product_History));Tijdgebonden koppelingen: twee tabellen op tijd uitlijnen
Een veelvoorkomende uitdaging is het koppelen van twee temporele tabellen op overeenkomende tijdsperioden. Denk bijvoorbeeld aan het koppelen van salarissen van werknemers aan afdelingsindelingen wanneer beide geldigheidsperioden hebben. Je koppelt op entiteitssleutel EN overlappingsvoorwaarde met && voor bereiken, of met expliciete datumvergelijkingen.
CREATE TABLE dept_assignment (
employee_id INT,
department VARCHAR(50),
valid_period DATERANGE
);
INSERT INTO dept_assignment VALUES
(1, 'Engineering', '[2020-01-01, infinity)'),
(1, 'Marketing', '[2019-01-01, 2020-01-01)');
-- Periods where employee 1 was in Engineering AND had salary > 55000
SELECT s.salary, d.department,
s.valid_period * d.valid_period AS overlap_period
FROM employee_salary_v2 s
JOIN dept_assignment d
ON s.employee_id = d.employee_id
AND s.valid_period && d.valid_period
WHERE s.employee_id = 1
AND s.salary > 55000;Hiaten en overlappingen voorkomen
Twee veelvoorkomende problemen met de gegevenskwaliteit in temporele tabellen zijn hiaten (perioden zonder record) en overlappingen (twee rijen die gelijktijdig geldig zijn). De uitsluitingsbeperking met && voorkomt overlappingen op databaseniveau. Voor het detecteren van hiaten moet je met een query controleren of er ontbrekende dekking is.
-- Find gaps in salary history for employee 1
-- (periods where upper(prev) < lower(next))
SELECT
upper(a.valid_period) AS gap_start,
lower(b.valid_period) AS gap_end
FROM employee_salary_v2 a
JOIN employee_salary_v2 b
ON a.employee_id = b.employee_id
AND upper(a.valid_period) < lower(b.valid_period)
WHERE a.employee_id = 1
AND NOT EXISTS (
SELECT 1 FROM employee_salary_v2 c
WHERE c.employee_id = 1
AND lower(c.valid_period) > upper(a.valid_period)
AND lower(c.valid_period) < lower(b.valid_period)
)
ORDER BY gap_start;Kennistoets
Test je kennis van temporele tabellen en query's voor een bepaald moment.
Samenvatting: temporele en versiebeheerste rijen
In deze les heb je geleerd hoe je tijdsafhankelijke gegevens modelleert met kolommen voor geldigheidstijd en het PostgreSQL-type daterange. Belangrijkste punten:
- Historische rijen nooit overschrijven — sluit de oude rij af en voeg een nieuwe versie in.
- Gebruik query's voor een bepaald moment (
valid_from <= target AND valid_to > target) om gegevens op elk moment in het verleden op te vragen. - Het type
daterangemet de operator@>maakt query's voor tijdsgegevens beknopt en leesbaar. - Uitsluitingsbeperkingen op
&&(overlap van bereiken) waarborgen de gegevensintegriteit op databaseniveau. - Tijdgebonden koppelingen brengen twee geschiedenissen met elkaar in lijn door hun geldigheidsperioden te kruisen.
Deze patronen vormen de basis van event sourcing, auditregistratie en elk systeem waarin historische nauwkeurigheid belangrijk is.
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 “Tijdelijke en versiebeheerste rijen” gratis?
Ja — de volledige tekst van “Tijdelijke en versiebeheerste rijen” 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 “Tijdelijke en versiebeheerste rijen”?
Query's op geldige tijd en op een bepaald tijdstip 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 3 van 4.
Hoe lang duurt de les “Tijdelijke en versiebeheerste rijen”?
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