ProgrammatieT-SQL ontwikkelaar / ETL engineer

Hoe voer je effectieve iteratie- en vertakkingverwerking (lussen, CASE, GOTO) uit in T-SQL (Transact-SQL)? Wanneer is het gebruik ervan gerechtvaardigd en wat zijn de aandachtspunten voor de prestaties?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

Achtergrond van de vraag:
Standaard SQL is oorspronkelijk ontworpen als een declaratieve taal zonder elementen van klassieke programmering (lussen, vertakkingen, directe sprongen), maar met uitbreidingen zoals T-SQL/PLSQL zijn constructies zoals WHILE, CASE, en zelfs een imitatie van GOTO beschikbaar gekomen.

Probleem:
Iteratieve bewerkingen (lussen door individuele records) leiden vaak tot traagheid, vooral bij het verwerken van grote hoeveelheden data, als je ze niet vervangt door een "set-based" benadering. Vertakkingen, CASE, IF — zijn erg handig, maar bij overmatige nesting lijdt de leesbaarheid en voorspelbaarheid van de code.

Oplossing:
Het gebruik van controleconstructies moet alleen gerechtvaardigd zijn wanneer batchverwerking (bulk/set) niet mogelijk is! Voor complexe berekeningen — een kleine lus, trigger of CASE is toegestaan. Voor massabewerking — is het beter om vensterfuncties of UPDATE met een subquery te gebruiken.

Voorbeeldcode (T-SQL):

DECLARE @i INT = 1 WHILE (@i <= 5) BEGIN IF @i % 2 = 0 PRINT CONCAT('Even: ', @i) ELSE PRINT CONCAT('Oneven: ', @i) SET @i = @i + 1 END

CASE-expressie:

SELECT num, CASE WHEN num % 2 = 0 THEN 'even' ELSE 'oneven' END AS parity FROM numbers

Belangrijke kenmerken:

  • Gebruik van lussen en vertakkingen is gerechtvaardigd voor sequentiële verwerking, niet toepasbaar voor miljoenen rijen
  • CASE-expressies zijn goed voor rij-voor-rij markering, maar vervangen geen aggregatie/vensterfuncties
  • In de meeste gevallen is een set-based benadering voordeliger: met één UPDATE of INSERT

Misleidende vragen.

Kan CASE worden gebruikt voor het filteren van rijen, net als WHERE?

Nee! CASE geeft verschillende waarden terug, maar filtert geen rijen. Een veelgemaakte fout is om via CASE te "filteren" in plaats van WHERE, het resultaat zal onjuist zijn.

Wat is het verschil tussen WHILE en CURSOR — is het niet hetzelfde?

WHILE is een basale lus, met handmatige controle van de variabele; CURSOR werkt op tabelrecords, houdt een verwijzing naar de rij vast. CURSOR is meer resource-intensief, werkt vaak veel langzamer voor grote datasets.

Welke benadering is sneller voor massaverwerking: WHILE-lus met UPDATE of één set-based UPDATE?

In 99% van de gevallen is één set-based UPDATE (of INSERT) veel sneller dan een lus over één record (ook al lijkt het flexibeler).

-- Onjuiste benadering DECLARE @id INT = 1 WHILE (@id <= 100000) BEGIN UPDATE t SET flag=1 WHERE id=@id SET @id = @id + 1 END -- Correct UPDATE t SET flag=1 WHERE id BETWEEN 1 AND 100000

Typische fouten en anti-patronen

  • Overmatig gebruik van lussen/WHILE voor massabewerkingen
  • Gebruik van GOTO om uit geneste blokken te springen (verstoort de logica van het programma)
  • CASE wordt niet gebruikt voor waarde-conversie, maar voor filtering
  • "Tunnel logica" via veel geneste IF...

Levensvoorbeeld

Negatieve case

In een project voor het bijwerken van de status van een miljoen bestellingen werd een lus met UPDATE voor elke id geschreven. De verwerking duurde ~8 uur. Bij een crash halverwege — verloren we alles, en moesten we handmatig herstellen.

Voordelen:

  • Eenvoudige debugging op kleine volumes

Nadelen:

  • Gigantische verwerkingstijd
  • Moeilijk te schalen
  • Hoge kans op inconsistentie bij falen

Positieve case

Omgezet naar set-based UPDATE met één expressie. De uitvoeringstijd werd teruggebracht tot 6 minuten, de verwerking is atomair.

Voordelen:

  • Veel sneller
  • Eenvoudig om de transactie als geheel te controleren
  • Eenvoudig onderhoud

Nadelen:

  • Logica is moeilijk "te customizen" voor elke individuele rij
  • Beperkingen bij te "flexibele" controles die alleen in een lus kunnen worden uitgevoerd