在表中进行 Ascii 和数字插入

问题描述 投票:0回答:1

我有一个名为 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;

你能帮我吗?

sql sql-server
1个回答
0
投票

这些程序感觉问题过于复杂了。您可以使用计数来向桌子添加更多行和过道,然后使用单个

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;
© www.soinside.com 2019 - 2024. All rights reserved.