SQLShack (Nederlands)
SQL Server-cursors zijn een veel voorkomend onderwerp op internet . U zult verschillende meningen vinden wanneer u ze wel en niet moet gebruiken. Vandaag zullen we er ook over praten en de vraag beantwoorden wanneer we ze (niet) moeten gebruiken.
Het gegevensmodel en het algemene idee
In het vorige artikel, Inleiding tot SQL Serverloops, we hadden het over SQL Server-loops, maar we hebben geen gegevens uit de database gebruikt. Dat was vreemd, maar dat zou nu veel duidelijker moeten worden. Nu we cursors uitleggen, zullen we de gegevens uit de database gebruiken om te laten zien wanneer we cursors wel of niet moeten gebruiken. Het gegevensmodel dat we zullen gebruiken, is hetzelfde dat we in deze serie gebruiken.
SQL Server ondersteunt 3 verschillende implementaties van cursors – Transact-SQL-cursors, API-cursors en Client-cursors. In dit artikel zullen we ons concentreren op Transact-SQL-cursors. U herkent ze gemakkelijk omdat ze zijn gebaseerd op de DECLARE CURSOR-syntaxis.
SQL Server Cursor – Inleiding
Voordat we naar code en voorbeelden gaan, moeten we uitleggen welke SQL Server-cursors zijn.
De SQL Server-cursor is T-SQL-logica, waarmee we het gerelateerde queryresultaat kunnen doorlopen. Dit stelt ons in staat om de acties opeenvolgend uit te voeren – bijv. Een update op een enkele rij uitvoeren.
Soms kan dit nuttig (lijken) te zijn, maar wanneer u met databases werkt, moet u geen procedurele programmeerpatronen gebruiken maar blijf liever bij declaratieve programmering. Een van de belangrijkste redenen is dat DBMSen al zijn geoptimaliseerd om acties uit te voeren op gegevenssets, en daarom zou u niet degene moeten zijn die probeert “slimmer te zijn dan het systeem”.
Toch is het goed om te weten hoe ze werken. Als er niets anders is, kom je ze misschien tegen in de code die je erft, en moet je de logica herschrijven. En voordat je iets doet, moet je begrijpen hoe het werkt.
Dus, voor het geval je cursors nodig hebt, is dit wat je erover moet weten:
- Cursors gebruiken variabelen om waarden op te slaan die in elk deel van de lus worden geretourneerd. Daarom moet je DECLARE alle variabelen die je nodig hebt
- Het volgende dat je moet doen, is DECLARE … CURSOR FOR SELECT-query, waar je een cursor declareert en ook de query definieert die betrekking heeft op (het vullen van) die cursor
- Je opent de cursor en FETCH NEXT vanaf de cursor
- In de WHILE-lus test je de @@ FETCH_STATUS variabele (WHILE @@ FETCH_STATUS = 0). Als de voorwaarde klopt, Ik kom in de lus BEGIN … END-blok en voer instructies uit binnen dat blok
- Nadat je de hele resultatenset hebt doorlopen, verlaat je de lus. U moet de cursor SLUITEN en DEALLOCEREN. Het vrijgeven van toewijzing is belangrijk omdat hierdoor de cursordefinitie wordt verwijderd en het gebruikte geheugen wordt vrijgemaakt.
SQL Server Cursor – Voorbeelden
Laten we nu twee cursorvoorbeelden bekijken. Hoewel ze vrij eenvoudig zijn, leggen ze mooi uit hoe cursors werken.
In het eerste voorbeeld willen we alle steden-ids en namen krijgen, samen met hun gerelateerde landnamen. We gebruiken de opdracht PRINT om combinaties af te drukken in elke doorgang van de lus.
Met behulp van de SQL Server-cursor en de while loop heeft precies teruggegeven wat we hadden verwacht – ids en namen van alle steden en gerelateerde landen die we in de database hebben.
Het belangrijkste om hier te vermelden is dat we deze resultatenset eenvoudig kunnen retourneren met de originele SQL-query die is opgeslagen in het DECLARE-gedeelte van de cursor, dus er was geen cursor nodig.
We gaan met nog een voorbeeld. Deze keer zullen we de informatieschemadatabase doorzoeken om de eerste 5 tabellen te retourneren, gesorteerd op tabelnaam. Hoewel het niet veel zin heeft om een dergelijke zoekopdracht te gebruiken, laat dit voorbeeld u zien:
- Hoe u de informatieschemadatabase opvraagt
- Hoe u een paar commandos / uitspraken combineert. zijn genoemd in eerdere artikelen (IF… ELSE, WHILE loop, CONCAT)
Van de codeerzijde, Ik zou willen benadrukken dat we deze keer niets in een lus hebben afgedrukt, maar eerder een string hebben gemaakt met CONCAT. We hebben ook de IF-instructie gebruikt om te testen of we in de eerste doorgang zitten, en als dat het geval is, hebben we geen “,” toegevoegd. Anders zouden we “,” aan de string toevoegen.
Na de lus hebben we de resultaatstring afgedrukt, de cursor gesloten en de locatie van de cursor opgeheven.
We zouden dit kunnen bereiken met de functie STRING_AGG. Deze is beschikbaar vanaf SQL Server 2017 en is het equivalent van de MySQL GROUP_CONCAT-functie.
SQL Server Cursor – Wanneer (niet) om ze te gebruiken?
Ik zal proberen om geef een objectief antwoord op de vraag – “Wanneer moet u SQL Server-cursors gebruiken en wanneer niet?”? Aangezien dingen in de loop van de tijd veranderen en verbeteringen zullen worden aangebracht, hetzij op cursors, hetzij op andere objecten die ze “vervangen”, dient u rekening te houden met de datum waarop dit artikel is geschreven.Dus laten we beginnen.
Gebruik geen cursors:
- Bijna altijd 🙂 Dit klinkt misschien stom, maar dat is in de meeste gevallen waar. SQL Server implementeert een groot aantal objecten & -functies die precies doen wat u waarschijnlijk zou proberen op te lossen met cursors. Voordat u besluit om met de cursor mee te gaan, moet u ervoor zorgen dat u genoeg onderzoek heeft gedaan om te concluderen dat de cursor de enige mogelijke (goede) oplossing is. Hetzelfde staat voor loops in databases. In het vorige artikel, Inleiding tot SQL Server-lussen, hebben we lussen gebruikt, maar niet om gegevens door te lussen.
Je zou cursors kunnen gebruiken:
- Meestal voor databasebeheertaken zoals back-ups, integriteitscontroles, opnieuw opbouwen van indexen
- Voor eenmalig taken waarvan u zeker weet dat mogelijke slechte prestaties geen invloed hebben op de algehele systeemprestaties.
-
Een opgeslagen procedure een paar keer aanroepen met verschillende parameters. In dat geval krijgt u parameters van cursorvariabelen en voert u oproepen uit binnen de lus
Het aanroepen van een opgeslagen procedure of een andere query binnen de cursor (of lus) heeft veel invloed op de prestaties, omdat in elke stap van de lus cursor loop, voer je de query / procedure vanaf het begin uit. Als u besluit dat te doen, moet u zich bewust zijn van de mogelijke gevolgen.
- De vorige hint brengt ons bij de laatste opsommingsteken wanneer u cursors zou moeten gebruiken. Als u zich volledig bewust bent van hoe ze werken en u er vrij zeker van bent dat dit geen invloed heeft op de prestaties, ga ervoor
SQL Server Cursor – Waarom mensen ze (niet) gebruiken ?
De laatste vraag die ik zou willen beantwoorden is: waarom zou iemand een cursor gebruiken? Dit is hoe ik het zie:
- Mensen die ze gebruiken voor eenmalige klussen of regelmatige acties waarbij ze geen invloed hebben op de prestaties, hebben het excuus. Een van de redenen is dat dergelijke code procedurele code is, en als je eraan gewend bent, is hij erg leesbaar.
- Aan de andere kant kunnen degenen die zijn begonnen met leren over databases en gewend zijn aan procedureel programmeren gebruik cursors omdat ze, zoals gezegd, veel dichter bij procedureel programmeren dan bij databases staan. Dit is geen reden om ze te gebruiken, omdat het enige excuus hier zou zijn dat je simpelweg niet de andere (juiste) manier weet om dingen gedaan te krijgen.
- Het belangrijkste van cursors is dat ze zijn traag in vergelijking met SQL-instructies, en daarom moet u het gebruik ervan vermijden, omdat ze vroeg of laat tot prestatieproblemen zullen leiden (tenzij u precies weet wat u doet en waarom).
I vind het handig dat je het concept van cursors begrijpt, want de kans is groot dat je ze onderweg tegenkomt. Ze waren populair voordat er enkele nieuwe opties aan SQL Server werden toegevoegd. Er is ook een kans dat u doorgaat met werken aan een systeem waarop iemand voordat u ze gebruikte, en u moet doorgaan waar ze zijn gestopt. Misschien moet je de cursor (procedurele code) vervangen door SQL (declaratieve code).
Conclusie
Er is geen betere conclusie over cursors dan – gebruik ze niet 🙂 SQL Server heeft veel veranderingen doorgevoerd die problemen oplossen die voorheen moeilijk op te lossen waren met declaratieve code. Het is beter wat tijd te besteden aan het onderzoeken en leren van iets nieuws, en tot slot, het produceren van optimale code. Je kunt ze natuurlijk gebruiken als je weet waarom je dat doet en als je je bewust bent van mogelijke problemen die ermee verband houden.
Inhoudsopgave
Leer SQL : CREATE DATABASE & CREATE TABLE Operations
Leer SQL: INSERT IN TABLE
Leer SQL: Primary Key
SQL leren: externe sleutel
SQL leren: instructie SELECT
SQL leren: INNER JOIN versus LEFT JOIN
SQL leren: SQL-scripts
SQL leren: soorten relaties
SQL leren: meerdere tabellen samenvoegen
SQL leren: geaggregeerde functies
SQL leren: hoe schrijf je een complexe SELECT-query?
SQL leren: de INFORMATION_SCHEMA-database
SQL leren: SQL-gegevenstypen
SQL leren: set-theorie
SQL leren: door de gebruiker gedefinieerde functies
SQL leren: door de gebruiker gedefinieerde opgeslagen procedures
SQL leren: SQL-weergaven
SQL leren: SQL-triggers
SQL leren: SQL-querys oefenen
SQL leren: SQL-queryvoorbeelden
SQL leren: handmatig een rapport maken met SQL-querys
SQL leren: SQL Server-datum- en tijdfuncties
SQL leren: SQL Server-rapporten maken datum- en tijdfuncties gebruiken
SQL leren: SQL Server-draaitabellen
SQL leren: SQL Server exporteren naar Excel
SQL leren: inleiding tot SQL Server-lussen
SQL leren: SQL Server-cursors
SQL leren: SQL-best practices voor het verwijderen en bijwerken van gegevens
SQL leren: naamgevingsconventies
SQL leren: SQL-gerelateerde taken
SQL leren: niet-Equi-joins in SQL Server
SQL leren: SQL-injectie
- Auteur
- Recente berichten
Zijn vroegere en huidige opdrachten variëren van database-ontwerp en codering tot lesgeven, adviseren en schrijven over databases. Ook niet te vergeten, BI, algoritmes maken, schaken, filatelie, 2 honden, 2 katten, 1 vrouw, 1 baby …
Je kunt hem vinden op LinkedIn
Bekijk alle berichten van Emil Drkusic
- SQL leren: SQL-injectie – 2 november 2020
- SQL leren: niet-Equi joins in SQL Server – 29 september 2020
- SQL leren: SQL-gerelateerde vacatures – 1 september 2020