我有一个名为 Locations 的表,用于存储超市的过道和行。
超市ID | 过道 | 行 |
---|---|---|
细胞1 | 细胞2 | 细胞3 |
5 号小区 | 5 号小区 | 6 号电池 |
最初,我的位置表中没有给定超市的条目。使用我创建的存储过程,我将在位置表中插入表示该超市的过道和行数的数据。 过道由字母(A、B、C...)表示,而行由数字(1、2、3...)表示 例如,对于超市 1,最初有 2 个过道和 3 行,完成的插入将为:
超市ID | 过道 | 行 |
---|---|---|
1 | A | 1 |
1 | A | 2 |
1 | A | 3 |
1 | B | 1 |
1 | B | 2 |
1 | B | 3 |
现在我想为超市添加额外的过道或行。我有 2 个存储过程来执行此操作。 例如,如果我想将过道数量增加到 4 个,行数增加到 5 个,则插入可以正确完成。 我的过道 A - D 每个有 1 - 5 行
但是如果我想添加额外的过道和行,即总共设置为 5 个过道和 6 行,我得到的插入是。
A - F 过道,每排 6 排。
我以某种方式获得了额外的过道。 以下是我的存储过程:
CREATE OR ALTER PROCEDURE [dbo].[SP_UPDATE_LOCATIONS]
@supermarketId BIGINT, -- Warehouse Id
@noAisles BIGINT, -- New number of aisles
@noRows BIGINT -- New number of rows
AS
BEGIN
DECLARE @oldNoAisles BIGINT;
DECLARE @oldNoRows BIGINT;
SELECT
@oldNoAisles = WAR.Aisles,
@oldNoRows = WAR.Rows
FROM SUPERMARKTETS WAR
WHERE WAR.SupermarketId = @supermarketId
IF (@oldNoRows > @noRows)
BEGIN
DELETE FROM AR_WAREHOUSE_LOCATIONS
WHERE SupermarketId = @supermarketId
AND WAL_N_ROW = @oldNoRows;
END
ELSE
BEGIN
--EXECUTE [dbo].[AR_SP_ADD_WAREHOUSE_LOCATIONS] @supermarketId, @noAisles, @noRows
EXECUTE [dbo].[SP_ADD_LOCATIONS] @supermarketId, @oldNoAisles, @noRows
END
IF (@oldNoAisles > @noAisles)
BEGIN
DECLARE @aisleToDelete VARCHAR(50) = CHAR(@oldNoAisles + 64);
DELETE FROM AR_WAREHOUSE_LOCATIONS
WHERE SupermarketId = @supermarketId
AND WAL_CH_AISLE = @aisleToDelete;
END
ELSE
BEGIN
EXECUTE [dbo].[SP_ADD_LOCATIONS] @supermarketId, @noAisles, @noRows
END
UPDATE SUPERMARKTETS
SET Aisles = @noAisles,
Rows = @noRows
WHERE SupermarketId = @supermarketId;
END;
还有
CREATE OR ALTER PROCEDURE [dbo].[SP_ADD_LOCATIONS]
@supermarketId bigint,
@NewAisleCount bigint,
@NewRowCount bigint
AS
BEGIN
-- Determine the starting aisle for new aisles (e.g., 'D' for the 4th aisle)
DECLARE @StartingAisle nvarchar(50);
SET @StartingAisle = CHAR(ASCII('A') + (SELECT MAX(ASCII(Aisles)) - ASCII('A') + 1 FROM Locations WHERE SupermarketId = @supermarketId));
-- Insert new aisles and rows for the new aisles
DECLARE @NewAisle nvarchar(50);
SET @NewAisle = @StartingAisle;
DECLARE @RowNumber bigint;
SET @RowNumber = 1;
WHILE @RowNumber <= @NewRowCount
BEGIN
INSERT INTO Locations (SupermarketId, Aisles, Rows)
VALUES (@supermarketId, @NewAisle, @RowNumber);
SET @RowNumber = @RowNumber + 1;
END;
-- Insert rows for existing aisles
DECLARE @ExistingAisle nvarchar(50);
SET @ExistingAisle = 'A';
WHILE ASCII(@ExistingAisle) <= ASCII(@StartingAisle)
BEGIN
DECLARE @RowCount bigint;
SET @RowCount = (SELECT MAX(Rows) FROM Locations WHERE SupermarketId = @supermarketId AND Aisles = @ExistingAisle);
WHILE @RowCount < @NewRowCount
BEGIN
INSERT INTO Locations (SupermarketId, Aisles, Rows)
VALUES (@supermarketId, @ExistingAisle, @RowCount + 1);
SET @RowCount = @RowCount + 1;
END;
SET @ExistingAisle = CHAR(ASCII(@ExistingAisle) + 1);
END;
END;
你能帮我吗?
这些程序感觉问题过于复杂了。您可以使用计数来向桌子添加更多行和过道,然后使用单个
INSERT
。也许是这样的:
CREATE OR ALTER PROC dbo.AddAislesRows @SupermarketID int, @Aisles tinyint, @Rows tinyint AS --Why a BIGINT? What happens when you get to aisle 27, let alone aisle 2,147,483,648?
BEGIN
INSERT INTO dbo.SuperMarketAisles (SupermarketID, Aisle, Row)
SELECT @SupermarketID,
CHAR(ASCII(M.MaxAisle)+A.value),
M.MaxRow + R.value
FROM GENERATE_SERIES(1,@Aisles) AS A
CROSS JOIN GENERATE_SERIES(1,@Rows) R
CROSS APPLY (SELECT MAX(Aisle) AS MaxAisle,
MAX(Row) AS MaxRow
FROM dbo.SuperMarketAisles SMA WITH (UPDLOCK)
WHERE SMA.SupermarketID = @SupermarketID) M; --Assumes a supermarket already has at least one row and aisle
END;
如果您没有使用 SQL Server 2022+,则需要使用 UDF,例如我下面写的:
CREATE OR ALTER FUNCTION [fn].[Tally] (@LastNumber bigint, @Zero bit)
RETURNS table
AS RETURN
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
SELECT 0 AS I
WHERE @Zero = 0
AND @LastNumber IS NOT NULL
UNION ALL
SELECT TOP (ISNULL(@LastNumber,0))
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
FROM N N1, N N2, N N3, N N4, N N5, N N6, N N7) --Up to 10,000,000 rows
SELECT I
FROM Tally T;
GO
CREATE OR ALTER PROC dbo.AddAislesRows @SupermarketID int, @Aisles tinyint, @Rows tinyint AS --Why a BIGINT? What happens when you get to aisle 27, let alone aisle 2,147,483,648?
BEGIN
INSERT INTO dbo.SuperMarketAisles (SupermarketID, Aisle, Row)
SELECT @SupermarketID,
CHAR(ASCII(M.MaxAisle)+A.value),
M.MaxRow + R.value
FROM fn.Tally(@Aisles,1) AS A
CROSS JOIN fn.Tally(@Rows,1) R
CROSS APPLY (SELECT MAX(Aisle) AS MaxAisle,
MAX(Row) AS MaxRow
FROM dbo.SuperMarketAisles SMA WITH (UPDLOCK)
WHERE SMA.SupermarketID = @SupermarketID) M;
END;