sql >> Database >  >> RDS >> Database

Hoe SQL-cursors voor speciale doeleinden te gebruiken

Dit artikel beschrijft SQL-cursors en hoe u ze voor een aantal speciale doeleinden kunt gebruiken. Het benadrukt het belang van SQL-cursors samen met hun nadelen.

Het is niet altijd zo dat u SQL-cursor gebruikt bij het programmeren van databases, maar hun conceptueel begrip en het leren gebruiken ervan helpt veel om te begrijpen hoe u uitzonderlijke taken kunt uitvoeren bij T-SQL-programmering.

Overzicht SQL-cursors

Laten we enkele basisprincipes van SQL-cursors doornemen als u er niet bekend mee bent.

Eenvoudige definitie

Een SQL-cursor geeft rij voor rij toegang tot gegevens, waardoor u meer (rij-voor-rij) controle over de resultatenset krijgt.

Microsoft-definitie

Volgens Microsoft-documentatie produceren Microsoft SQL Server-instructies een volledige resultatenset, maar er zijn momenten waarop de resultaten het beste rij voor rij kunnen worden verwerkt. Door een cursor op een resultatenset te openen, kan de resultaatset rij voor rij worden verwerkt.

T-SQL en resultatenset

Aangezien zowel een eenvoudige als Microsoft-definitie van de SQL-cursor een resultatenset vermelden, laten we proberen te begrijpen wat de resultatenset precies is in de context van databaseprogrammering. Laten we snel als volgt de tabel Studenten maken en vullen in een voorbeelddatabase UniversityV3:

CREATE TABLE [dbo].[Student] ( [StudentId] INT IDENTITY (1, 1) NOT NULL, [Name] VARCHAR (30) NULL, [Course] VARCHAR (30) NULL, [Marks] INT NULL, [ExamDate] DATETIME2 (7) NULL, CONSTRAINT [PK_Student] PRIMARY KEY CLUSTERED ([StudentId] ASC));-- (5) Vul Student-tabelSET IDENTITY_INSERT [dbo].[Student] ONINSERT INTO [dbo].[Student] ( [StudentId], [Naam], [Cursus], [Markeringen], [ExamDatum]) WAARDEN (1, N'Asif', N'Database Management System', 80, N'2016-01-01 00:00:00 ')INSERT INTO [dbo].[Student] ([StudentId], [Name], [Course], [Marks], [ExamDate]) WAARDEN (2, N'Peter', N'Database Management System', 85, N'2016-01-01 00:00:00')INSERT INTO [dbo].[Student] ([StudentId], [Name], [Course], [Marks], [ExamDate]) WAARDEN (3, N' Sam', N'Database Management System', 85, N'2016-01-01 00:00:00')INSERT INTO [dbo].[Student] ([StudentId], [Name], [Course], [Marks ], [Examendatum]) WAARDEN (4, N'Adil', N'Database Management System', 85, N'2016-01-01 00:00:00 ')INSERT INTO [dbo].[Student] ([StudentId], [Name], [Course], [Marks], [ExamDate]) WAARDEN (5, N'Naveed', N'Database Management System', 90, N'2016-01-01 00:00:00')SET IDENTITY_INSERT [dbo].[Student] UIT

Selecteer nu alle rijen van de Leerling tafel:

-- Bekijk studententabelgegevensSELECT [StudentId], [Name], [Course], [Marks], [ExamDate] FROM dbo.Student

Dit is de resultatenset die wordt geretourneerd als resultaat van het selecteren van alle records van de Student tafel.

T-SQL en verzamelingentheorie

T-SQL is puur gebaseerd op de volgende twee wiskundige concepten:

  1. Set-theorie
  2. Predikaatlogica

De verzamelingenleer is, zoals de naam al aangeeft, een tak van de wiskunde over verzamelingen die ook verzamelingen van bepaalde onderscheiden objecten kunnen worden genoemd.

Kortom, in de verzamelingenleer denken we over dingen of objecten als geheel op dezelfde manier als we aan een individueel item denken.

De student is bijvoorbeeld een verzameling van alle duidelijk onderscheiden studenten, dus we nemen een student als geheel, wat voldoende is om details te krijgen van alle studenten in die set (tabel).

Raadpleeg mijn artikel De kunst van het aggregeren van gegevens in SQL van eenvoudige tot glijdende aggregaties voor meer informatie.

Cursors en op rijen gebaseerde bewerkingen

T-SQL is in de eerste plaats ontworpen om op sets gebaseerde bewerkingen uit te voeren, zoals het selecteren van alle records uit een tabel of het verwijderen van alle rijen uit een tabel.

Kortom, T-SQL is speciaal ontworpen om op een set-gebaseerde manier met tabellen te werken, wat betekent dat we denken aan een tabel als een geheel, en elke bewerking zoals selecteren, bijwerken of verwijderen wordt in zijn geheel toegepast op de tabel of bepaalde rijen die aan de criteria voldoen.

Er zijn echter gevallen waarin tabellen rij voor rij moeten worden geopend in plaats van als één enkele resultaatset, en dit is wanneer cursors in actie komen.

Volgens Vaidehi Pandere moet applicatielogica soms met één rij tegelijk werken in plaats van alle rijen tegelijk, wat hetzelfde is als lussen (gebruik van lussen om te herhalen) door de hele resultatenset.

Basisprincipes van SQL-cursors met voorbeelden

Laten we het nu hebben over SQL-cursors.

Laten we allereerst (degenen die al bekend zijn met het gebruik van cursors in T-SQL) leren of bekijken hoe ze de cursor in T-SQL kunnen gebruiken.

Het gebruik van de SQL-cursor is een proces van vijf stappen dat als volgt wordt uitgedrukt:

  1. Cursor declareren
  2. Cursor openen
  3. Rijen ophalen
  4. Cursor sluiten
  5. Cursor toewijzen opheffen

Stap 1:Cursor declareren

De eerste stap is het declareren van de SQL-cursor zodat deze daarna kan worden gebruikt.

SQL-cursor kan als volgt worden gedeclareerd:

DECLARE Cursor  voor 

Stap 2:Cursor openen

De volgende stap na de aangifte is het openen van de cursor, wat betekent dat de cursor wordt gevuld met de resultatenset die als volgt wordt uitgedrukt:

Open 

Stap 3:rijen ophalen

Zodra de cursor is gedeclareerd en geopend, is de volgende stap het één voor één ophalen van rijen van de SQL-cursor, zodat rijen ophalen de volgende beschikbare rij van de SQL-cursor krijgt:

Volgende ophalen van 

Stap 4:Cursor sluiten

Zodra de rijen één voor één zijn opgehaald en volgens de vereisten zijn gemanipuleerd, is de volgende stap het sluiten van de SQL-cursor.

Het sluiten van de SQL-cursor voert drie taken uit:

  1. Maakt de resultaatset vrij die momenteel door de cursor wordt vastgehouden
  2. Bevrijd alle cursorvergrendelingen op de rijen met de cursor
  3. Sluit de open cursor

De eenvoudige syntaxis voor het sluiten van de cursor is als volgt:

Sluit 

Stap 5:de toewijzing van de cursor opheffen

De laatste stap in dit opzicht is het ongedaan maken van de toewijzing van de cursor die de cursorreferentie verwijdert.

De syntaxis is als volgt:

DEALLOCATE 

SQL-cursorcompatibiliteit

Volgens Microsoft-documentatie zijn SQL-cursors compatibel met de volgende versies:

  1. SQL Server 2008 en hogere versies
  2. Azure SQL-database

SQL-cursor Voorbeeld 1:

Nu we bekend zijn met de stappen die nodig zijn om de SQL-cursor te implementeren, laten we eens kijken naar een eenvoudig voorbeeld van het gebruik van de SQL-cursor:

-- Voorbeeld van studentcursor declareren 1GEBRUIK UniversityV3GODECLARE Student_Cursor CURSOR VOOR SELECT StudentId ,[Name]FROM dbo.Student;OPEN Student_CursorFETCH NEXT FROM Student_CursorWHILE @@FETCH_STATUS =0BEGINFETCH VOLGENDE Student_CursATE 

De uitvoer is als volgt:

SQL-cursor Voorbeeld 2:

In dit voorbeeld gaan we twee variabelen gebruiken om de gegevens op te slaan die door de cursor worden vastgehouden terwijl deze van rij naar rij gaat, zodat we de resultatenset rij voor rij kunnen weergeven door de waarden van de variabelen weer te geven.

-- Declareer Student-cursor met variabelen voorbeeld 2USE UniversityV3GODECLARE @StudentId INT ,@StudentName VARCHAR(40) -- Declareer variabelen die rijgegevens bevatten die worden vastgehouden door cursorDECLARE Student_Cursor CURSOR VOOR SELECT StudentId ,[Name]FROM dbo.Student;OPEN Student_CursorFETCH NEXT FROM Student_Cursor INTO @StudentId, @StudentName -- Haal de eerste rij op en sla deze op in variabelenWHILE @@FETCH_STATUS =0BEGINPRINT CONCAT(@StudentId,'--', @StudentName) -- Toon variabelen dataFETCH NEXT FROM Student_Cursor -- Haal de volgende rij gegevens in cursor en sla deze op in variabelenINTO @StudentId, @StudentNameENDCLOSE Student_Cursor -- Sluit cursorvergrendelingen op de rijenDEALLOCATE Student_Cursor -- Laat cursorreferentie los

Het resultaat van de bovenstaande SQL-code is als volgt:

Je zou kunnen stellen dat we dezelfde output kunnen bereiken door een eenvoudig SQL-script als volgt te gebruiken:

-- Student-ID en naam bekijken zonder SQL-cursorSELECT StudentId,Name FROM dbo.Studentorder door StudentId

In feite zijn er nogal wat taken waarvoor SQL-cursors moeten worden gebruikt, ondanks het feit dat het gebruik van SQL-cursors wordt afgeraden vanwege hun directe invloed op het geheugen.

Belangrijke opmerking

Houd er rekening mee dat volgens Vaidehi Pandere, cursors een geheugenresidente set aanwijzers zijn, zodat ze uw systeemgeheugen in beslag nemen dat anders door andere belangrijke processen zou worden gebruikt; daarom is het nooit een goed idee om een ​​grote resultatenset via cursors te doorlopen, tenzij daar een legitieme reden voor is.

SQL-cursors gebruiken voor speciale doeleinden

We zullen enkele speciale doeleinden doornemen waarvoor SQL-cursors kunnen worden gebruikt.

Database server geheugen testen

Aangezien SQL-cursors een grote impact hebben op het systeemgeheugen, zijn ze goede kandidaten om scenario's te repliceren waarin overmatig geheugengebruik door verschillende opgeslagen procedures of ad-hoc SQL-scripts moet worden onderzocht.

Een eenvoudige manier om dit te begrijpen, is door op de knop voor clientstatistieken op de werkbalk te klikken (of door op Shift+Alt+S te drukken) in SSMS (SQL Server Management Studio) en een eenvoudige query uit te voeren zonder cursor:

Voer nu de query uit met de cursor met behulp van variabelen (SQL Cursor Voorbeeld 2):

Noteer nu de verschillen:

Aantal SELECT-instructies zonder cursor:1

Aantal SELECT-instructies met cursor:7

Aantal server-roundtrips zonder cursor:1

Aantal server-roundtrips met cursor:2

Klantverwerkingstijd zonder cursor:1

Klantverwerkingstijd met cursor:8

Totale uitvoeringstijd zonder cursor:1

Totale uitvoeringstijd met cursor:38

Wachttijd op serverantwoorden zonder cursor:0

Wachttijd op serverantwoorden met cursor:30

Kortom, het uitvoeren van de query zonder de cursor die slechts 5 rijen retourneert, is het 6-7 keer uitvoeren van dezelfde query met de cursor.

Nu kun je je voorstellen hoe gemakkelijk het is om geheugenimpact te repliceren met behulp van cursors, maar dit is niet altijd het beste om te doen.

Manipulatietaken voor bulkdatabaseobjecten

Er is een ander gebied waar SQL-cursors handig kunnen zijn en dat is wanneer we een bulkbewerking moeten uitvoeren op databases of database-objecten.

Om dit te begrijpen, moeten we eerst de cursustabel maken en deze invullen in de UniversityV3 database als volgt:

-- Cursustabel makenCREATE TABLE [dbo].[Course] ( [CourseId] INT IDENTITY (1, 1) NOT NULL, [Name] VARCHAR (30) NOT NULL, [Detail] VARCHAR (200) NULL, CONSTRAINT [PK_Course] PRIMARY KEY CLUSTERED ([CourseId] ASC));-- Cursustabel invullenSET IDENTITY_INSERT [dbo].[Course] ONINSERT INTO [dbo].[Course] ([CourseId], [Name], [Detail]) WAARDEN (1, N'DevOps for Databases', N'This is about DevOps for Databases')INSERT INTO [dbo].[Course] ([CourseId], [Name], [Detail]) WAARDEN (2, N'Power BI Fundamentals', N'This is about Power BI Fundamentals')INSERT INTO [dbo].[Course] ([CourseId], [Name], [Detail]) VALUES (3, N'T-SQL Programming', N'About T-SQL Programming')INSERT INTO [dbo].[Course] ([CourseId], [Name], [Detail]) VALUES (4, N'Tabular Data Modeling', N'This is about Tabular Data Modeling')INSERT INTO [dbo].[Course] ([CourseId], [Name], [Detail]) VALUES (5, N'Analysis Services Fundamentals', N'This gaat about Analysis Services Fundamentals')SET IDENTITY_INSERT [dbo].[Cursus] UIT

Stel nu dat we alle bestaande tabellen in de UniversityV3 . willen hernoemen database als OUDE tabellen.

Dit vereist een herhaling van de cursor over alle tabellen, één voor één, zodat ze kunnen worden hernoemd.

De volgende code doet het werk:

-- Verklaar Student cursor om alle tabellen te hernoemen als oldUSE UniversityV3GODECLARE @TableName VARCHAR(50) -- Bestaande tabelnaam ,@NewTableName VARCHAR(50) -- Nieuwe tabelnaamDECLARE Student_Cursor CURSOR VOOR SELECTEER T.TABLE_NAME FROM INFORMATION_SCHEMA.TABLES T;OPEN Student_CursorFETCH NEXT FROM Student_Cursor INTO @TableNameWHILE @@FETCH_STATUS =0BEGINSET @[email protected]+'_OLD' -- Voeg _OLD toe aan de bestaande naam van de tabelEXEC sp_rename @TableName,@CH_CH_STATUS - Rename Student-tabel als OXTableName -- Zet de volgende rijgegevens in de cursor en sla deze op in variabelenINTO @TableNameENDCLOSE Student_Cursor -- Sluit de cursorvergrendelingen op de rijenDEALLOCATE Student_Cursor -- Laat cursorreferentie los

Gefeliciteerd, je hebt met succes alle bestaande tabellen hernoemd met de SQL-cursor.

Dingen om te doen

Nu u bekend bent met het gebruik van de SQL-cursor, kunt u het volgende proberen:

  1. Probeer met de cursor indexen van alle tabellen van een voorbeelddatabase aan te maken en te hernoemen.
  2. Probeer de hernoemde tabellen in dit artikel terug te zetten naar de oorspronkelijke namen met de cursor.
  3. Probeer tabellen met veel rijen te vullen en meet de statistieken en tijd voor de zoekopdrachten met en zonder de cursor.


  1. Geekbench 3 gebruiken om de prestaties van de databaseserver te evalueren

  2. oracle PL/SQL hoe bereik ip te berekenen voor IPv6 cidr

  3. MySQL SELECT stapteller

  4. SQL Sentry is nu SentryOne