Volgnummers

Van toepassing op:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceSQL-database in Microsoft Fabric

In dit artikel wordt uitgelegd hoe u volgnummers gebruikt in SQL Server, Azure SQL Database en Azure SQL Managed Instance. Een reeks is een door de gebruiker gedefinieerd schemagebonden object dat een reeks numerieke waarden genereert op basis van de specificatie waarmee de reeks is gemaakt.

Overzicht

De reeks numerieke waarden wordt gegenereerd in een oplopende of aflopende volgorde met een bepaald interval en kan zich herhalen zoals aangevraagd. Reeksen, in tegenstelling tot identiteitskolommen, worden niet gekoppeld aan tabellen. Een toepassing verwijst naar een reeksobject om de volgende waarde te ontvangen. De relatie tussen reeksen en tabellen wordt beheerd door de toepassing. Gebruikerstoepassingen kunnen verwijzen naar een reeksobject en de waardensleutels coördineren voor meerdere rijen en tabellen.

Een reeks wordt onafhankelijk van de tabellen gemaakt met behulp van de CREATE SEQUENCE instructie. Met opties kunt u de incrementele, maximum- en minimumwaarden, het beginpunt, de mogelijkheid voor automatisch opnieuw opstarten en caching beheren om de prestaties te verbeteren. Zie CREATE SEQUENCEvoor meer informatie over de opties.

In tegenstelling tot waarden voor identiteitskolommen, die worden gegenereerd wanneer rijen worden ingevoegd, kan een toepassing het volgende volgnummer verkrijgen voordat de rij wordt ingevoegd door de VOLGENDE WAARDE VOOR functie aan te roepen. Het volgnummer wordt toegewezen wanneer NEXT VALUE FOR aangeroepen wordt, zelfs als het getal nooit in de tabel wordt ingevoegd. De NEXT VALUE FOR functie kan worden gebruikt als de standaardwaarde voor een kolom in een tabeldefinitie. Gebruik sp_sequence_get_range om een bereik van meerdere reeksnummers tegelijk op te halen.

Een reeks kan worden gedefinieerd als een gegevenstype van het type geheel getal. Als het gegevenstype niet is opgegeven, wordt een reeks standaard ingesteld op bigint.

Reeksen gebruiken

Gebruik reeksen in plaats van identiteitskolommen in de volgende scenario's:

  • Voor de toepassing is een getal vereist voordat de invoeging in de tabel wordt gemaakt.

  • Voor de toepassing moet één reeks getallen tussen meerdere tabellen of meerdere kolommen in een tabel worden gedeeld.

  • De toepassing moet de nummerreeks opnieuw starten wanneer een opgegeven getal is bereikt. Nadat u bijvoorbeeld waarden 1 tot en met 10 hebt toegewezen, wordt de toepassing gestart met het opnieuw toewijzen van waarden 1 tot en met 10.

  • Voor de toepassing moeten sequentiewaarden worden gesorteerd op een ander veld. De NEXT VALUE FOR functie kan de OVER component toepassen op de functie-aanroep. De OVER clausule garandeert dat de geretourneerde waarden worden gegenereerd in de volgorde van de OVER clausule's ORDER BY clausule.

  • Voor een toepassing moeten meerdere nummers tegelijk worden toegewezen. Een toepassing moet bijvoorbeeld vijf opeenvolgende getallen reserveren. Het aanvragen van identiteitswaarden kan leiden tot hiaten in de reeks als er gelijktijdig in andere processen nummers worden opgevraagd. Het aanroepen van sp_sequence_get_range kan meerdere nummers in de reeks tegelijk ophalen.

  • U moet de specificatie van de reeks wijzigen, zoals de incrementele waarde.

Beperkingen

In tegenstelling tot identiteitskolommen, waarvan de waarden niet kunnen worden gewijzigd, worden reekswaarden niet automatisch beveiligd na invoeging in de tabel. Als u wilt voorkomen dat reekswaarden worden gewijzigd, gebruikt u een updatetrigger in de tabel om wijzigingen terug te draaien.

Uniekheid wordt niet automatisch afgedwongen voor reekswaarden. De mogelijkheid om reekswaarden opnieuw te gebruiken, is standaard. Als reekswaarden in een tabel uniek moeten zijn, maakt u een unieke beperking voor de kolom. Als reekswaarden in een tabel uniek moeten zijn in een groep tabellen, maakt u triggers om dubbele waarden te voorkomen die worden veroorzaakt door update-instructies of het cycliren van reeksnummers.

Het reeksobject genereert getallen volgens de definitie, maar het reeksobject bepaalt niet hoe de getallen worden gebruikt. Reeksnummers die in een tabel zijn ingevoegd, kunnen hiaten hebben wanneer een transactie wordt teruggedraaid, wanneer een reeksobject wordt gedeeld door meerdere tabellen of wanneer reeksnummers worden toegewezen zonder deze in tabellen te gebruiken. Wanneer de CACHE optie wordt gebruikt, kan een onverwachte uitschakeling, zoals een stroomstoring, leiden tot verlies van de volgnummers in de cache.

Als er meerdere exemplaren van de NEXT VALUE FOR functie zijn die dezelfde reeksgenerator binnen één Transact-SQL instructie opgeven, retourneren al deze exemplaren dezelfde waarde voor een bepaalde rij die door die Transact-SQL instructie is verwerkt. Dit gedrag is consistent met de ANSI-standaard.

Reeksnummers worden gegenereerd buiten het bereik van de huidige transactie. Ze worden verbruikt of de transactie met behulp van het volgnummer wordt doorgevoerd of teruggedraaid. Dubbele validatie vindt alleen plaats zodra een record volledig is ingevuld. Dit kan leiden tot sommige gevallen waarbij hetzelfde getal wordt gebruikt voor meer dan één record tijdens het maken, maar vervolgens wordt geïdentificeerd als een duplicaat. Als dit gebeurt en andere autonummeringswaarden zijn toegepast op volgende records, kan dit leiden tot een tussenruimte tussen autonummeringswaarden.

Typisch gebruik

Als u een geheel getal wilt maken dat wordt verhoogd met 1 van -2.147.483.648 tot 2.147.483.647, gebruikt u de volgende instructie.

CREATE SEQUENCE Schema.SequenceName
    AS INT
    INCREMENT BY 1;

Als u een gehele getallenreeks wilt maken die lijkt op een identiteitskolom die met 1 wordt verhoogd van 1 tot 2.147.483.647, gebruikt u de volgende opdracht.

CREATE SEQUENCE Schema.SequenceName
    AS INT
    START WITH 1
    INCREMENT BY 1;

Reeksen beheren

Voor informatie over reeksen voert u een query uit sys.sequences.

Voorbeelden

Er zijn meer voorbeelden in de artikelen CREATE SEQUENCE, NEXT VALUE FOR en sp_sequence_get_range.

Een. Een volgnummer in één tabel gebruiken

In het volgende voorbeeld wordt een schema gemaakt met de naam Test, een tabel met de naam Orders en een reeks met de naam CountBy1en voegt u vervolgens rijen in de tabel in met behulp van de NEXT VALUE FOR functie.

CREATE SCHEMA Test;
GO

CREATE TABLE Test.Orders
(
    OrderID INT PRIMARY KEY,
    Name VARCHAR (20) NOT NULL,
    Qty INT NOT NULL
);
GO

CREATE SEQUENCE Test.CountBy1
    START WITH 1
    INCREMENT BY 1;
GO

INSERT Test.Orders (OrderID, Name, Qty)
VALUES (NEXT VALUE FOR Test.CountBy1, 'Tire', 2);

INSERT test.Orders (OrderID, Name, Qty)
VALUES (NEXT VALUE FOR Test.CountBy1, 'Seat', 1);

INSERT test.Orders (OrderID, Name, Qty)
VALUES (NEXT VALUE FOR Test.CountBy1, 'Brake', 1);

SELECT *
FROM Test.Orders;

Dit is de resultaatset.

OrderID  Name   Qty
-------- ------ ---
1        Tire    2
2        Seat    1
3        Brake   1

B. De volgende waarde aanroepen voordat u een rij invoegt

Met behulp van de Orders tabel die in voorbeeld A is gemaakt, declareert het volgende voorbeeld een variabele met de naam @nextIDen gebruikt u vervolgens de NEXT VALUE FOR functie om de variabele in te stellen op het volgende beschikbare volgnummer. De toepassing wordt verwacht om een bepaalde verwerking van de order uit te voeren, zoals het verstrekken van het OrderID-nummer aan de klant en vervolgens de bestelling te valideren. Ongeacht hoe lang deze verwerking kan duren of hoeveel andere orders er tijdens het proces worden toegevoegd, blijft het oorspronkelijke nummer behouden voor gebruik door deze verbinding. Ten slotte voegt de INSERT-instructie de volgorde toe aan de tabel Orders.

DECLARE @NextID AS INT;
SET @NextID = NEXT VALUE FOR Test.CountBy1;

INSERT Test.Orders (OrderID, Name, Qty)
VALUES (@NextID, 'Rim', 2);

C. Een volgnummer in meerdere tabellen gebruiken

In dit voorbeeld wordt ervan uitgegaan dat een bewakingsproces via een productielijn meldingen ontvangt van gebeurtenissen die zich in de hele workshop voordoen. Elke gebeurtenis ontvangt een uniek en monotonisch toenemend EventID getal. Alle gebeurtenissen gebruiken hetzelfde EventID volgnummer, zodat rapporten die alle gebeurtenissen combineren, elke gebeurtenis uniek kunnen identificeren. De gebeurtenisgegevens worden echter opgeslagen in drie verschillende tabellen, afhankelijk van het type gebeurtenis. In het codevoorbeeld wordt een schema gemaakt met de naam Audit, een reeks met de naam EventCounteren drie tabellen die elk de EventCounter reeks als standaardwaarde gebruiken. Vervolgens worden in het voorbeeld rijen toegevoegd aan de drie tabellen en worden de resultaten opgevraagd.

CREATE SCHEMA Audit;
GO

CREATE SEQUENCE Audit.EventCounter
    AS INT
    START WITH 1
    INCREMENT BY 1;
GO

CREATE TABLE Audit.ProcessEvents
(
    EventID INT DEFAULT ( NEXT VALUE FOR Audit.EventCounter) PRIMARY KEY CLUSTERED,
    EventTime DATETIME DEFAULT (getdate()) NOT NULL,
    EventCode NVARCHAR (5) NOT NULL,
    Description NVARCHAR (300) NULL
);
GO

CREATE TABLE Audit.ErrorEvents
(
    EventID INT DEFAULT ( NEXT VALUE FOR Audit.EventCounter) PRIMARY KEY CLUSTERED,
    EventTime DATETIME DEFAULT (getdate()) NOT NULL,
    EquipmentID INT NULL,
    ErrorNumber INT NOT NULL,
    EventDesc NVARCHAR (256) NULL
);
GO

CREATE TABLE Audit.StartStopEvents
(
    EventID INT DEFAULT ( NEXT VALUE FOR Audit.EventCounter) PRIMARY KEY CLUSTERED,
    EventTime DATETIME DEFAULT (getdate()) NOT NULL,
    EquipmentID INT NOT NULL,
    StartOrStop BIT NOT NULL
);
GO

INSERT Audit.StartStopEvents (EquipmentID, StartOrStop)
VALUES (248, 0);

INSERT Audit.StartStopEvents (EquipmentID, StartOrStop)
VALUES (72, 0);

INSERT Audit.ProcessEvents (EventCode, Description)
VALUES (2735, 'Clean room temperature 18 degrees C.');

INSERT Audit.ProcessEvents (EventCode, Description)
VALUES (18, 'Spin rate threshold exceeded.');

INSERT Audit.ErrorEvents (EquipmentID, ErrorNumber, EventDesc)
VALUES (248, 82, 'Feeder jam');

INSERT Audit.StartStopEvents (EquipmentID, StartOrStop)
VALUES (248, 1);

INSERT Audit.ProcessEvents (EventCode, Description)
VALUES (1841, 'Central feed in bypass mode.');

SELECT EventID,
       EventTime,
       Description
FROM Audit.ProcessEvents
UNION
SELECT EventID,
       EventTime,
       EventDesc
FROM Audit.ErrorEvents
UNION
SELECT EventID,
       EventTime,
       CASE StartOrStop WHEN 0 THEN 'Start' ELSE 'Stop' END
FROM Audit.StartStopEvents
ORDER BY EventID;

Dit is de resultaatset.

EventID     EventTime               Description
----------- ----------------------- ------------------------------------
1           2025-12-09 17:41:57.350 Start
2           2025-12-09 17:41:57.350 Start
3           2025-12-09 17:41:57.350 Clean room temperature 18 degrees C.
4           2025-12-09 17:41:57.350 Spin rate threshold exceeded.
5           2025-12-09 17:41:57.350 Feeder jam
6           2025-12-09 17:41:57.350 Stop
7           2025-12-09 17:41:57.350 Central feed in bypass mode.

D. Herhalende volgnummers genereren in een resultatenset

In het volgende voorbeeld ziet u twee functies van reeksnummers: fietsen en het gebruik van NEXT VALUE FOR in een select-instructie.

CREATE SEQUENCE CountBy5
    AS TINYINT
    START WITH 1
    INCREMENT BY 1
    MINVALUE 1
    MAXVALUE 5
    CYCLE;
GO

SELECT NEXT VALUE FOR CountBy5 AS SurveyGroup,
       Name
FROM sys.objects;

E. Volgnummers genereren voor een resultatenset met behulp van de OVER-component

In het volgende voorbeeld wordt de component OVER gebruikt om de resultatenset te sorteren op Name voordat de kolom met het volgnummer wordt toegevoegd.

USE AdventureWorks2022;
GO

CREATE SCHEMA Samples;
GO

CREATE SEQUENCE Samples.IDLabel
    AS TINYINT
    START WITH 1
    INCREMENT BY 1;
GO

SELECT NEXT VALUE FOR Samples.IDLabel OVER (ORDER BY Name) AS NutID,
       ProductID,
       Name,
       ProductNumber
FROM Production.Product
WHERE Name LIKE '%nut%';

F. Het volgnummer opnieuw instellen

Voorbeeld E heeft de eerste 79 van de Samples.IDLabel reeksnummers gebruikt. (Uw versie van AdventureWorks2025 kan een ander aantal resultaten retourneren.) Voer het volgende uit om de volgende 79 reeksnummers (80 tot en met 158) te gebruiken.

SELECT NEXT VALUE FOR Samples.IDLabel OVER (ORDER BY Name) AS NutID,
       ProductID,
       Name,
       ProductNumber
FROM Production.Product
WHERE Name LIKE '%nut%';

Voer de volgende instructie uit om de Samples.IDLabel reeks opnieuw op te starten.

ALTER SEQUENCE Samples.IDLabel
    RESTART WITH 1;

Voer de select-instructie opnieuw uit om te controleren of de Samples.IDLabel reeks opnieuw is opgestart met nummer 1.

SELECT NEXT VALUE FOR Samples.IDLabel OVER (ORDER BY Name) AS NutID,
       ProductID,
       Name,
       ProductNumber
FROM Production.Product
WHERE Name LIKE '%nut%';

G. Een tabel wijzigen van identiteit in volgorde

In het volgende voorbeeld wordt een schema en tabel gemaakt met drie rijen voor het voorbeeld. Vervolgens wordt in het voorbeeld een nieuwe kolom toegevoegd en wordt de oude kolom verwijderd.

CREATE SCHEMA Test;
GO

CREATE TABLE Test.Department
(
    DepartmentID SMALLINT IDENTITY (1, 1) NOT NULL,
    Name NVARCHAR (100) NOT NULL,
    GroupName NVARCHAR (100) NOT NULL CONSTRAINT PK_Department_DepartmentID PRIMARY KEY CLUSTERED (DepartmentID ASC)
);
GO

INSERT Test.Department (Name, GroupName)
VALUES ('Engineering', 'Research and Development');
GO

INSERT Test.Department (Name, GroupName)
VALUES ('Tool Design', 'Research and Development');
GO

INSERT Test.Department (Name, GroupName)
VALUES ('Sales', 'Sales and Marketing');
GO

SELECT *
FROM Test.Department;
GO

ALTER TABLE Test.Department
    ADD DepartmentIDNew SMALLINT NULL;
GO

UPDATE Test.Department
    SET DepartmentIDNew = DepartmentID;
GO

ALTER TABLE Test.Department DROP CONSTRAINT [PK_Department_DepartmentID];
ALTER TABLE Test.Department DROP COLUMN DepartmentID;
GO

EXECUTE sp_rename 'Test.Department.DepartmentIDNew', 'DepartmentID', 'COLUMN';
GO

ALTER TABLE Test.Department ALTER COLUMN DepartmentID SMALLINT NOT NULL;

ALTER TABLE Test.Department
    ADD CONSTRAINT PK_Department_DepartmentID PRIMARY KEY CLUSTERED (DepartmentID ASC);

SELECT MAX(DepartmentID)
FROM Test.Department;

CREATE SEQUENCE Test.DeptSeq
    AS SMALLINT
    START WITH 4
    INCREMENT BY 1;
GO

ALTER TABLE Test.Department
    ADD CONSTRAINT DefSequence DEFAULT ( NEXT VALUE FOR Test.DeptSeq) FOR DepartmentID;
GO

SELECT DepartmentID,
       Name,
       GroupName
FROM Test.Department;

INSERT Test.Department (Name, GroupName)
VALUES ('Audit', 'Quality Assurance');
GO

SELECT DepartmentID,
       Name,
       GroupName
FROM Test.Department;

Transact-SQL instructies die SELECT * gebruiken, ontvangen de nieuwe kolom als de laatste, in plaats van als de eerste kolom. Als dit niet acceptabel is, moet u een geheel nieuwe tabel maken, de gegevens naar de tabel verplaatsen en vervolgens de machtigingen voor de nieuwe tabel opnieuw maken.