herkusg - Wednesday, February 21, 2018 4:26 PM
One way to achieve this is to use a "Tracking Table" where you have a row for each Company-Warehouse combination, and keep a record of the last used number.
Use a proc to update the number, and return the number to the calling process.
NOTE: This can lead to hot-spotting. However, since you are using Access, I assume that the volume will be low, and you should be OK.CREATE TABLE dbo.NextID (
Company CHAR(2) NOT NULL
, Warehouse CHAR(3) NOT NULL
, NextID INT NOT NULL
, CONSTRAINT PK_NextID PRIMARY KEY CLUSTERED(Company, Warehouse)
);
GO
CREATE PROCEDURE dbo.GetNextID
@Company CHAR(2)
, @Warehouse CHAR(3)
, @NextID INT OUTPUT
AS
BEGIN
-- Ensure that there is a record for the provided Company-Warehouse combination
INSERT INTO dbo.NextID (Company, Warehouse, NextID)
SELECT @Company, @Warehouse, 0
WHERE NOT EXISTS (SELECT 1 FROM dbo.NextID AS n WITH (XLOCK, HOLDLOCK)
WHERE n.Company = @Company
AND n.Warehouse = @Warehouse);
-- Use a quirky Update to get the next ID
UPDATE dbo.NextID
SET @NextID = NextID = NextID + 1
WHERE Company = @Company
AND Warehouse = @Warehouse;
END;
GO
DECLARE @Company CHAR(2) = 'AU';
DECLARE @Warehouse CHAR(3) = 'w01';
DECLARE @NextID INT;
EXEC dbo.GetNextID
@Company = @Company
, @Warehouse = @Warehouse
, @NextID = @NextID OUTPUT;
SELECT
Company = @Company
, Warehouse = @Warehouse
, NextID = @NextID;
GO
Since this is a SQL 2014 board, I am assuming that you are on SQL 2014.
In that case, an alternate method is to dynamically create a sequence object for each Company-Warehouse combination.
You also create a proc to get the next number, but there is no tracking table.CREATE PROCEDURE dbo.GetNextSEQ
@Company CHAR(2)
, @Warehouse CHAR(3)
, @NextID INT OUTPUT
AS
BEGIN
DECLARE @SQL NVARCHAR(4000);
DECLARE @SeqName SYSNAME = N'dbo.' + @Company + '_' + @Warehouse + '_SEQ' ;
-- Ensure that there is a dedicated sequence object for provided Company-Warehouse combination
SET @SQL = N'IF OBJECT_ID(N''' + @SeqName + N''', N''SO'') IS NULL
BEGIN
CREATE SEQUENCE ' + @SeqName + N'
AS INT
MINVALUE 1
START WITH 1
INCREMENT BY 1
NO CYCLE;
END;';
EXEC sys.sp_executesql @stmt = @SQL;
SET @SQL = N'SET @NextID = NEXT VALUE FOR ' + @SeqName + N';';
EXEC sys.sp_executesql
@stmt = @SQL
, @params = N'@NextID INT OUTPUT'
, @NextID = @NextID OUTPUT;
END;
GO
DECLARE @Company CHAR(2) = 'AU';
DECLARE @Warehouse CHAR(3) = 'w01';
DECLARE @NextID INT;
EXEC dbo.GetNextSEQ
@Company = @Company
, @Warehouse = @Warehouse
, @NextID = @NextID OUTPUT;
SELECT
Company = @Company
, Warehouse = @Warehouse
, NextID = @NextID;
GO
SELECT *
FROM sys.sequences AS s;