Unikaj konfliktów numerów z sekwencjami Microsoft SQL
Uwaga:Będę prezentować ten temat w grupie Dostęp z SQL Server online. Dołącz do mnie 13 września o 18:30 CST, dołącz do grupy, aby otrzymać wiadomość e-mail ze wszystkimi szczegółami spotkania, to nic nie kosztuje!
- Czy musisz zagwarantować, że liczba w polu zostanie użyta tylko raz i nigdy nie zostanie zduplikowana przez innego użytkownika?
- Czy zdarzyło Ci się, że potrzebowałeś więcej niż jednego autonumeru w tabeli?
- Czy kiedykolwiek potrzebowałeś dolnego i górnego limitu liczb sekwencyjnych i nie mogłeś go przekroczyć?
- Czy czasami masz listę numerów, które chcesz odzyskać, gdy miniesz ostatni?
W SQL Server istnieje funkcja, która może to całkiem łatwo obsłużyć i nazywa się to sekwencją. Jest dostępny od SQL Server 2012.
Podobnie jak automatyczny numer, może zapewnić, że za każdym razem zostanie nadany unikalny numer, chyba że zostanie poddany recyklingowi.
Ostatnio zostałem poproszony o zaimplementowanie sekwencji dla klienta, w której wielu użytkowników będzie tworzyło nowe rekordy i musiało „pobrać” kolejny numer w określonej kolejności. Nie mogliśmy użyć autonumerowania, ponieważ klient był ograniczony do pewnego zakresu, aby nie przekroczyć górnego progu. Kiedy numery się wyczerpią, kierownictwo uzupełni sekwencję od nowa.
Dlaczego używanie tabeli Access nie działa
Przed uaktualnieniem do SQL Server użytkownicy dzieliliby tabelę, która trzymałaby zakładki dotyczące następnego numeru do użycia, problem z tym podejściem polega na tym, że nie jest to niezawodne, dwóch użytkowników może zażądać tego samego numeru dokładnie w tym samym czasie, naruszające zasady biznesowe.
Tworzenie i używanie sekwencji serwera SQL
Zanim będzie można użyć sekwencji, należy ją utworzyć przy użyciu następującej składni w SQL Server, wystarczy to zrobić tylko raz:
CREATE SEQUENCE dbo.seqPolicyNumber AS int MIN 50005000 MAX 50005999;
Użyj następującej instrukcji, aby pobrać następny numer sekwencji:
SELECT NEXT VALUE FOR dbo.seqPolicyNumber as NextValue
Twoi użytkownicy będą potrzebować uprawnień do aktualizacji, aby używać sekwencji, ale nie powinni mieć możliwości zmiany zakresu sekwencji. Uprawnienia do aktualizacji można nadać przy użyciu następującej składni:
GRANT UPDATE ON dbo.seqPolicyNumber TO [MyDatabaseUserOrRole];
Aby uzyskać następną wartość sekwencji z programu Microsoft Access VBA, możesz użyć następującej instrukcji, aby wczytać następną wartość do zestawu rekordów ADODB.
strSQL = "SELECT NEXT VALUE FOR dbo.seqPolicyNumber as NextValue"
OpenMyRecordset rs, strSQL
NextValue = rs("NextValue")
W ten sposób zazwyczaj otwieramy zestaw rekordów ADODB w naszej firmie. Aby uzyskać więcej informacji na temat korzystania z OpenMyRecordset, możesz kliknąć inny artykuł na naszym blogu:
Łatwe zestawy rekordów i polecenia ADODB w programie Access
Zaletą składni do uzyskania kolejnego numeru sekwencyjnego jest to, że jest bardzo łatwa w użyciu w T-SQL. Po prostu podstawiasz NEXT VALUE FOR
INSERT dbo.Orders (OrderID, Name, Qty)
VALUES (NEXT VALUE FOR dbo.OrderNumberSequence, 'Tire', 2);
Większa elastyczność niż automatyczne numerowanie
Sekwencja może oferować większą elastyczność niż autonumerowanie w programie Access lub pole IDENTITY w programie SQL Server. Po pierwsze, w tabeli możesz mieć tylko jedno autonumerowanie lub pole tożsamości. Chociaż można ponownie umieścić pole IDENTITY, nie można przetwarzać wartości. Pola IDENTITY są nadal przydatne w przypadku kluczy podstawowych, gdy chcemy, aby jakaś dowolna liczba identyfikowała rekord, a nie ma to żadnego znaczenia. Jednak zakresy sekwencji mogą mieć osadzone znaczenie.
Nie jesteś również ograniczony do używania liczb całkowitych, takich jak TOŻSAMOŚĆ, ale liczby sekwencyjne mogą być również dziesiętne lub numeryczne. Możesz także zwiększać swoją sekwencję w dół zamiast tylko w górę.
Również sekwencja nie jest powiązana z żadną konkretną tabelą i może być używana w różnych tabelach, ponieważ dla konkretnej tabeli potrzebne są nowe numery sekwencji.
Uzupełnij sekwencję
Jeśli chcesz zmienić zakres sekwencji, na przykład gdy potrzebujesz nowego zakresu numerów zasad, należy to zrobić za pomocą procedury składowanej. Poniżej przedstawiono procedurę składowaną, która może to zrobić.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[usp_AlterPolicySequence] (
@SeqName AS nazwa_systemu,
@InpMin AS int,
@InpMax AS int
) Z WYKONAJ JAKO WŁAŚCICIEL AS
ROZPOCZNIJ
WŁĄCZ NR;
DECLARE @sql nvarchar(MAX),
@err nvarchar(MAX);
IF NOT EXISTS (
SELECT NULL
FROM sys.sequences AS s
WHERE s.name =@SeqName
AND s.schema_id =SCHEMA_ID('dbo')
)
THROW 50000, 'Nazwa sekwencji jest nieprawidłowa.', 1;
IF @InpMin JEST NULL LUB @InpMax JEST NULL
THROW 50000, „Wartości nie mogą być null.”, 1;
SET @sql =CONCAT(N'ALTER SEQUENCE [dbo].', QOTENAME(@SeqName), N' RESTART WITH ', @InpMin, N' INCREMENT O 1′, N' MINVALUE ', @InpMin, N' MAXVALUE ' , @InpMax, N' NO CYCLE NO CACHE;');
EXEC sys.sp_executesql @sql;
;
KONIEC
W tej procedurze składowanej warto zwrócić uwagę na kilka rzeczy. Najpierw uruchamiamy go
Z WYKONAJ JAKO WŁAŚCICIEL JAKO.
Nie chcemy, aby zwykły użytkownik mógł zmieniać sekwencję. Ale chcemy dać im ograniczone możliwości zmiany tego tylko za pomocą procedury składowanej. (Użytkownicy potrzebują tylko uprawnień do procedury składowanej.)
GRANT EXECUTE ON dbo.usp_AlterPolicySequence TO [MyDatabaseUserOrRole];
Tę procedurę składowaną można uruchomić z interfejsu programu Access za każdym razem, gdy zachodzi potrzeba zainstalowania nowego zakresu w sekwencji, co zwykle jest wykonywane przez administratora, który może mieć więcej uprawnień programu SQL Server niż zwykły użytkownik.
Jednak ta procedura składowana może być również uruchamiana, gdy nowy zakres numerów czeka na załadowanie do sekwencji, zaraz po zużyciu bieżącej sekwencji. W takim przypadku procedura składowana może zostać wywołana przez dowolnego użytkownika, który potrzebuje pierwszego numeru zasady dla nowego zakresu. Dlatego używamy opcji Z WYKONAJ JAKO WŁAŚCICIEL JAKO, aby dać im więcej praw tylko do tego ograniczonego użytku.
Inną rzeczą, na którą należy zwrócić uwagę, jest to, że konieczne jest skonstruowanie ciągu SQL, a następnie użycie
EXEC sys.sp_executesql
na tym ciągu, jeśli używamy parametrów.
Poniższa instrukcja zadziała, jeśli zostanie wpisana do okna zapytania SSMS lub użyta w procedurze składowanej.
ALTER SEQUENCE dbo.seqPolicyNumber
RESTART WITH 50005000
INCREMENT BY 1
MINVALUE 50005000
MAXVALUE 50005999
NO CYCLE
NO CACHE
Jednak poniższe nie będą działać przy użyciu parametrów w procedurze składowanej.
ALTER SEQUENCE dbo.seqPolicyNumber
RESTART WITH @InpMin
INCREMENT BY 1
MINVALUE @InpMin
MAXVALUE @InpMax
NO CYCLE
NO CACHE
Musisz więc skonstruować instrukcję ciągu z wklejonymi wartościami parametrów.
SET @sql = CONCAT(N'ALTER SEQUENCE [dbo].', QUOTENAME(@SeqName), N' RESTART WITH ', @InpMin, N' INCREMENT BY 1', N' MINVALUE ', @InpMin, N' MAXVALUE ', @InpMax, N' NO CYCLE NO CACHE;');
EXEC sys.sp_executesql @sql;
Ten ciąg @sql jest tworzony przy użyciu funkcji CONCAT i QUOTENAME. Zadziała również, jeśli użyłeś znaków plus do utworzenia końcowego ciągu, ale lepiej zrobić to tak, jak w przykładzie, który jest bezpieczny dla wartości Null.
Ta procedura składowana spowoduje (zgłosi) błąd, jeśli podasz brakujące lub złe wartości i nie będziesz mógł kontynuować. Automatycznie wygeneruje błąd, jeśli wszystkie numery sekwencyjne zostaną zużyte.
Twoja procedura dostępu frontonu powinna sprawdzić, czy nie wystąpił błąd, który powinien wystąpić tylko wtedy, gdy w sekwencji zabraknie liczb, jeśli podajesz odpowiednie dane wejściowe parametrów. Jeśli zostanie zauważony błąd, interfejs będzie musiał jakoś anulować swoje działanie.
Istnieje kilka innych możliwości, które można ustawić za pomocą argumentów. CYCLE pozwoli na ponowne wykonanie cyklu po osiągnięciu końca, a następnie przejście do MIN.WARTOŚCI. Możesz nawet jawnie zrestartować go w środku sekwencji, nadając mu wartość RESTART.
Możesz również nadać mu pamięć podręczną, na przykład możesz poprosić o 50 numerów sekwencji na raz i aktualizować tabele sekwencji systemu raz na 50 numerów, co może być szybsze, ale zwiększa również ryzyko w przypadku awarii zasilania , ponieważ te numery nie mogą być ponownie użyte
Ostatnią rzeczą wartą odnotowania w tej procedurze składowanej jest to, że możesz pobrać informacje (metadane) o sekwencjach z widoku systemowego zwanego sys.sequences. Zawiera następujące informacje.
Niektóre przydatne kolumny, które warto przeczytać i przekazać użytkownikowi, to minimalna_wartość, maksymalna_wartość i aktualna_wartość.
Jeśli jesteś zainteresowany, poniższe strony w MSDN zawierają bardzo przydatne informacje na temat sekwencji.
Numery sekwencji
Opisuje sekwencje i zawiera bardzo dobre przykłady typowego zastosowania
UTWÓRZ SEKWENCJĘ (Transact-SQL)
ZMIANA SEKWENCJI (Transact-SQL)
NASTĘPNA WARTOŚĆ DLA (Transact-SQL)
sys.sequences (język Transact-SQL)
Opisuje metadane, których można użyć w swoich sekwencjach