I have a stored procedure and function on SQL Server. But, whenever I run it, I got some error like this
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
This is my function of CekStokTersedia (for checking available stock):
USE [Hotel]
GO
/****** Object: UserDefinedFunction [dbo].[CekStokTersedia] Script Date: 03/04/2023 12:20:08 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[CekStokTersedia] (@tglCheckin datetime, @tglCheckout datetime, @qty int, @kodeMenu varchar(100))
RETURNS bit
AS
BEGIN
DECLARE @stok float
DECLARE @results TABLE (STOK bit)
INSERT INTO @results (STOK)
SELECT CASE WHEN ISNULL(Stock_Akhir, 0) >= @qty THEN 1 ELSE 0 END AS STOK
FROM Tr_Type_S
WHERE T_Type = @kodeMenu AND tanggal >= @tglCheckin AND tanggal <= @tglCheckout
DECLARE @result bit
SELECT @result = STOK FROM @results WHERE STOK = 0
-- tambahkan kondisi pengecekan apakah ada data dengan range tanggal yang dimasukkan
IF NOT EXISTS (SELECT 1 FROM Tr_Type_S WHERE T_Type = @kodeMenu AND tanggal >= @tglCheckin AND tanggal <= @tglCheckout)
SET @result = 0
RETURN @result
END
Then, this is my stored procedure CheckStockMenu:
USE [Hotel]
GO
/****** Object: StoredProcedure [dbo].[CheckStockMenu] Script Date: 03/04/2023 12:20:29 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--EXEC [dbo].[CheckStockMenu] '2023-04-01', '2023-04-03', 'PA03,PA02', '2,10'
ALTER PROCEDURE [dbo].[CheckStockMenu]
@Checkin datetime,
@Checkout datetime,
@MenuKode varchar(100),
@qty varchar(100)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @stokTersedia bit = 1;
DECLARE @menuKodes TABLE (kode varchar(100), qty int);
DECLARE @menuKodeTidakCukup varchar(100) = '';
DECLARE @qtyInt AS int = (SELECT CAST(value AS int) FROM STRING_SPLIT(@qty, ','));
INSERT INTO @menuKodes (kode, qty)
SELECT kode.value, CAST(qty.value AS int)
FROM STRING_SPLIT(@MenuKode, ',') AS kode
JOIN STRING_SPLIT(@qty, ',') AS qty
ON kode.[key] = qty.[key]
DECLARE @kodesMenu varchar(100);
DECLARE menu_cursor CURSOR FOR SELECT kode FROM @menuKodes;
OPEN menu_cursor;
FETCH NEXT FROM menu_cursor INTO @kodesMenu;
WHILE @@FETCH_STATUS = 0
BEGIN
-- Pengecekan apakah data dengan range antara @Checkin dan @Checkout ada atau tidak
IF (SELECT COUNT(tanggal) FROM Tr_Type_S WHERE T_Type = @kodesMenu AND tanggal >= @Checkin AND tanggal <= @Checkout) <> DATEDIFF(day, @Checkin, @Checkout) + 1
BEGIN
SET @stokTersedia = 0;
SET @menuKodeTidakCukup = CONCAT(@menuKodeTidakCukup, @kodesMenu, ', ');
END
-- Pengecekan stok pada setiap menu yang dimasukkan
ELSE IF dbo.CekStokTersedia(@Checkin, @Checkout, @qtyInt, @kodesMenu) = 0
BEGIN
SET @stokTersedia = 0;
SET @menuKodeTidakCukup = CONCAT(@menuKodeTidakCukup, @kodesMenu, ', ');
END
FETCH NEXT FROM menu_cursor INTO @kodesMenu;
END
CLOSE menu_cursor;
DEALLOCATE menu_cursor;
IF @stokTersedia = 1
SELECT 'Stok tersedia' AS Status;
ELSE
SELECT CONCAT('Stok tidak cukup untuk menu dengan kode ', LEFT(@menuKodeTidakCukup, LEN(@menuKodeTidakCukup) - 1)) AS Status;
END
Then, I running the procedure like this:
EXEC [dbo].[CheckStockMenu] '2023-04-01', '2023-04-03', 'PA03,PA02', '2,10'
And have an error like this:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Please help me to solve this problem...
2条答案
按热度按时间vyu0f0g11#
i think the subquery returns more than one value -- but the code tries to compare it with a single value(the issue is related to the function
dbo.CekStokTersedia
which returns more than one value in certain scenarios)reason for the error could be the use of the
@qtyInt
parameter indbo.CekStokTersedia
@qtyInt
is a single integer value -- the query inside the function expects to compare it with multiple values from the Stock_Akhir (could lead to a subquery returning multiple values)Tr_Type_S
with two temporary tables@tglCheckin
and@tglCheckout
to get a list of dates between the check-in and check-out datesStock_Akhir
value for each date@results
(should return a single value)PS. you may want to review the use of cursors in the stored procedure(they can be a performance issue and can sometimes lead to unexpected results) -- it's better to use set-based operations instead of cursors -- especially for large datasets
ulmd4ohb2#
You are passing the value
'2,10'
for@qty
(i.e. two values) but try to assign this to a single int value here:What are you expecting
@qtyInt
to be here, 2 or 10, and why? You need to give SQL Server the correct logic to determine which value to chose as@qtyInt
can only hold one value.Although having looked through your procedure I don't think you need this assignment at all, your cursor already includes this quantity, so you can remove the problem line and just assign this within your cursor fetch:
Finally, while I am not familiar with all of your business logic, I'd be very surprised if this couldn't be rewritten a lot more efficiently using a set based approach. Procedural approaches like this typically do not scale well.