Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Dotyczy:SQL Server
Azure SQL Database
Azure SQL Managed Instance
Baza danych SQL w usłudze Microsoft Fabric
W tym artykule wyjaśniono, jak używać numerów sekwencji w programie SQL Server, usłudze Azure SQL Database i usłudze Azure SQL Managed Instance. Sekwencja to obiekt powiązany ze schematem zdefiniowany przez użytkownika, który generuje sekwencję wartości liczbowych zgodnie ze specyfikacją, z którą utworzono sekwencję.
Przegląd
Sekwencja wartości liczbowych jest generowana w kolejności rosnącej lub malejącej w zdefiniowanym interwale i może cyklicznie (powtarzać) zgodnie z żądaniem. Sekwencje, w przeciwieństwie do kolumn tożsamości, nie są skojarzone z tabelami. Aplikacja odwołuje się do obiektu sekwencji w celu otrzymania następnej wartości. Relacja między sekwencjami i tabelami jest kontrolowana przez aplikację. Aplikacje użytkownika mogą odwoływać się do obiektu sekwencji i koordynować klucze wartości w wielu wierszach i tabelach.
Sekwencja jest tworzona niezależnie od tabel przy użyciu instrukcji CREATE SEQUENCE . Opcje umożliwiają sterowanie przyrostem, maksymalnymi i minimalnymi wartościami, punktem początkowym, możliwością automatycznego ponownego uruchamiania i buforowaniem w celu zwiększenia wydajności. Aby uzyskać informacje o opcjach, zobacz CREATE SEQUENCE.
W przeciwieństwie do wartości kolumn tożsamości, które są generowane podczas wstawiania wierszy, aplikacja może uzyskać następny numer sekwencji przed wstawieniem wiersza, wywołując funkcję NEXT VALUE FOR. Numer sekwencji jest przydzielany, gdy NEXT VALUE FOR jest wywoływany, nawet jeśli liczba nigdy nie zostanie wstawiona do tabeli. Funkcja NEXT VALUE FOR może służyć jako wartość domyślna dla kolumny w definicji tabeli. Użyj sp_sequence_get_range, aby jednocześnie uzyskać zakres wielu liczb sekwencji.
Sekwencja może być zdefiniowana jako dowolny typ danych liczb całkowitych. Jeśli typ danych nie jest określony, sekwencja jest domyślnie ustawiona na bigint.
Używanie sekwencji
Użyj sekwencji zamiast kolumn tożsamości w następujących scenariuszach:
Aplikacja wymaga liczby przed wstawieniem do tabeli.
Aplikacja wymaga udostępniania jednej serii liczb między wieloma tabelami lub wieloma kolumnami w tabeli.
Aplikacja musi ponownie uruchomić serię numerów po osiągnięciu określonej liczby. Na przykład po przypisaniu wartości od 1 do 10 aplikacja ponownie zacznie przypisywać wartości od 1 do 10.
Aplikacja wymaga sortowania wartości sekwencji według innego pola. Funkcja
NEXT VALUE FORmoże zastosować klauzulęOVERdo wywołania funkcji. KlauzulaOVERgwarantuje, że wartości zwracane są generowane w kolejności klauzuliORDER BYklauzuliOVER.Aplikacja wymaga przypisania wielu liczb jednocześnie. Na przykład aplikacja musi zarezerwować pięć liczb sekwencyjnych. Żądanie wartości tożsamości może spowodować przerwy w serii, jeśli inne procesy jednocześnie przydzielono numery. Wywołanie
sp_sequence_get_rangemoże uzyskać kilka numerów w sekwencji jednocześnie.Należy zmienić specyfikację sekwencji, na przykład wartość przyrostu.
Ograniczenia
W przeciwieństwie do kolumn tożsamości, których wartości nie można zmienić, wartości sekwencji nie są automatycznie chronione po wstawieniu do tabeli. Aby zapobiec zmianie wartości sekwencji, użyj wyzwalacza aktualizacji w tabeli, aby wycofać zmiany.
Unikatowość nie jest automatycznie wymuszana dla wartości sekwencji. Możliwość ponownego użycia wartości sekwencji jest zamierzoną cechą. Jeśli wartości sekwencji w tabeli muszą być unikatowe, utwórz unikatowe ograniczenie w kolumnie. Jeśli wartości sekwencji w tabeli muszą być unikatowe w całej grupie tabel, utwórz wyzwalacze, aby zapobiec duplikatom spowodowanym przez instrukcje aktualizacji lub cykle numerów sekwencji.
Obiekt sekwencji generuje liczby zgodnie z definicją, ale obiekt sekwencji nie kontroluje sposobu użycia liczb. Numery sekwencji wstawione do tabeli mogą mieć luki, gdy transakcja jest wycofywana, gdy obiekt sekwencji jest współużytkowany przez wiele tabel lub gdy numery sekwencji są przydzielane bez ich używania w tabelach. Po utworzeniu z opcją CACHE, nieoczekiwane zamknięcie, takie jak awaria zasilania, może skutkować utratą numerów sekwencji w pamięci podręcznej.
Jeśli istnieje wiele wystąpień NEXT VALUE FOR funkcji określających ten sam generator sekwencji w ramach jednej instrukcji Transact-SQL, wszystkie te wystąpienia zwracają tę samą wartość dla danego wiersza przetworzonego przez tę instrukcję Transact-SQL. To zachowanie jest zgodne ze standardem ANSI.
Numery sekwencji są generowane poza zakresem bieżącej transakcji. Są one używane niezależnie od tego, czy transakcja przy użyciu numeru sekwencji została zatwierdzona, czy wycofana. Zduplikowana weryfikacja odbywa się tylko po pełnym wypełnieniu rekordu. Może to spowodować, że w niektórych przypadkach ta sama liczba jest używana dla więcej niż jednego rekordu podczas tworzenia, ale następnie jest identyfikowana jako duplikat. Jeśli tak się stanie i inne wartości autonumerowania zostaną zastosowane do kolejnych rekordów, może to spowodować przerwę między tymi wartościami.
Typowe użycie
Aby utworzyć liczbę całkowitą, która zwiększa się o 1 z -2 147 483 648 do 2147 483 483 647, użyj następującej instrukcji.
CREATE SEQUENCE Schema.SequenceName
AS INT
INCREMENT BY 1;
Aby utworzyć numer sekwencji całkowitej podobny do kolumny identyfikacyjnej, która zwiększa się o 1 od 1 do 2 147 483 647, użyj następującej instrukcji.
CREATE SEQUENCE Schema.SequenceName
AS INT
START WITH 1
INCREMENT BY 1;
Zarządzanie sekwencjami
Aby uzyskać informacje o sekwencjach, wykonaj zapytanie sys.sequences.
Przykłady
Więcej przykładów można znaleźć w artykułach CREATE SEQUENCE, NEXT VALUE FOR i sp_sequence_get_range.
A. Używanie numeru sekwencji w jednej tabeli
Poniższy przykład tworzy schemat o nazwie Test, tabelę o nazwie Orders i sekwencję o nazwie CountBy1, a następnie wstawia wiersze do tabeli przy użyciu NEXT VALUE FOR funkcji .
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;
Oto zestaw wyników.
OrderID Name Qty
-------- ------ ---
1 Tire 2
2 Seat 1
3 Brake 1
B. Wywołaj następną wartość parametru przed wstawieniem wiersza
Korzystając z tabeli utworzonej w przykładzie Orders A, poniższy przykład deklaruje zmienną o nazwie @nextID, a następnie używa NEXT VALUE FOR funkcji do ustawienia zmiennej na następny dostępny numer sekwencji. Aplikacja wykonuje pewne przetwarzanie zamówienia, takie jak dostarczenie klientowi numeru OrderID jego potencjalnego zamówienia, a następnie weryfikuje zamówienie. Niezależnie od tego, jak długo to przetwarzanie może potrwać lub ile innych zamówień jest dodawanych podczas procesu, oryginalny numer jest zachowywany do użytku przez to połączenie. Na koniec instrukcja INSERT dodaje kolejność do tabeli Orders.
DECLARE @NextID AS INT;
SET @NextID = NEXT VALUE FOR Test.CountBy1;
INSERT Test.Orders (OrderID, Name, Qty)
VALUES (@NextID, 'Rim', 2);
C. Używanie numeru sekwencji w wielu tabelach
W tym przykładzie przyjęto założenie, że proces monitorowania linii produkcyjnej odbiera powiadomienia o zdarzeniach występujących podczas warsztatów. Każde zdarzenie otrzymuje unikalny numer EventID, który zwiększa się w sposób monotoniczny. Wszystkie zdarzenia używają tego samego numeru sekwencji EventID, aby raporty, które łączą wszystkie zdarzenia, mogą jednoznacznie identyfikować każde zdarzenie. Jednak dane zdarzenia są przechowywane w trzech różnych tabelach, w zależności od typu zdarzenia. Przykładowy kod tworzy schemat o nazwie Audit, sekwencję o nazwie EventCounteri trzy tabele, które używają sekwencji EventCounter jako wartości domyślnej. Następnie przykład dodaje wiersze do trzech tabel i wykonuje zapytania dotyczące wyników.
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;
Oto zestaw wyników.
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. Generowanie powtarzających się numerów sekwencji w zestawie wyników
W poniższym przykładzie przedstawiono dwie cechy numerów sekwencji: cykliczność i użycie NEXT VALUE FOR w instrukcji select.
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. Generowanie numerów sekwencji dla zestawu wyników przy użyciu klauzuli OVER
W poniższym przykładzie użyto klauzuli OVER do sortowania zestawu wyników według Name przed dodaniem kolumny numeru sekwencji.
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. Resetowanie numeru sekwencji
Przykład E używał pierwszych 79 numerów sekwencji Samples.IDLabel. (Twoja wersja AdventureWorks2025 może zwrócić inną liczbę wyników). Wykonaj następujące czynności, aby użyć kolejnych 79 numerów sekwencji (od 80 do 158).
SELECT NEXT VALUE FOR Samples.IDLabel OVER (ORDER BY Name) AS NutID,
ProductID,
Name,
ProductNumber
FROM Production.Product
WHERE Name LIKE '%nut%';
Wykonaj następującą instrukcję, aby ponownie uruchomić sekwencję Samples.IDLabel.
ALTER SEQUENCE Samples.IDLabel
RESTART WITH 1;
Ponownie wykonaj instrukcję select, aby sprawdzić, czy sekwencja Samples.IDLabel została ponownie uruchomiona z numerem 1.
SELECT NEXT VALUE FOR Samples.IDLabel OVER (ORDER BY Name) AS NutID,
ProductID,
Name,
ProductNumber
FROM Production.Product
WHERE Name LIKE '%nut%';
G. Zmień tabelę z tożsamości na sekwencję
W poniższym przykładzie zostanie utworzony schemat i tabela zawierająca trzy wiersze dla przykładu. Następnie przykład dodaje nową kolumnę i odrzuca starą kolumnę.
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 instrukcje, które używają SELECT *, otrzymują nową kolumnę jako ostatnią kolumnę zamiast pierwszej. Jeśli nie jest to akceptowalne, musisz utworzyć zupełnie nową tabelę, przenieść do niej dane, a następnie utworzyć ponownie uprawnienia do nowej tabeli.