我正在做一个房间预定服务,除了预定房间之外,还将为会议保留一些必要的资源。
我有一个存储过程,该过程执行一些初步检查,完成后便进行房间预订(在Booking表中插入新行)。此后,资源保留过程开始。
对于每种类型的资源,我想知道有多少可用空间,因此我为此创建了一个函数。这就是发生奇怪行为的地方。
如果我从普通查询中调用该函数,它将返回要保留的空闲资源的数量。
但是,如果我调用内部调用此函数的存储过程,则该存储过程不会向我返回任何值,从而导致该过程失败。
我的主要存储过程是:
CREATE PROCEDURE [dbo].[Pr_SaveBooking]
@room_id INT = 0,
@start_date DATETIME,
@end_date DATETIME,
@resources BookingResourceType READONLY
AS
BEGIN
SET NOCOUNT ON;
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN TRANSACTION;
BEGIN TRY
DECLARE @id BIGINT;
-- Some checks
-- ...
-- ...
INSERT INTO Booking(room_id, start_date, end_date)
VALUES (@room_id, @start_date, @end_date);
IF (@@ROWCOUNT <= 0)
THROW 55008, 'Error', 1;
SELECT @id = SCOPE_IDENTITY();
PRINT CONCAT('Booking done (#', @id, ')')
EXEC Pr_InsertBookingResources @id, @resources, @start_date, @end_date;
PRINT 'BookingResources done'
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
PRINT 'Rollback';
THROW;
END CATCH
IF @@TRANCOUNT > 0
COMMIT TRANSACTION;
END
此过程称为另一个,它负责储备资源。
CREATE PROCEDURE [dbo].[Pr_InsertBookingResources]
@bookingId INT,
@resources BookingResourceType READONLY,
@startDate DATETIME,
@endDate DATETIME
AS
DECLARE @cursor CURSOR;
DECLARE @bookingResourceId INT;
DECLARE @resourceId INT;
DECLARE @amount INT;
DECLARE @amountFree INT;
BEGIN
-- For every resource
SET
@cursor = CURSOR
FOR
SELECT
bookingResource_id, resource_id, amount
FROM
@resources;
OPEN @cursor
FETCH NEXT FROM @cursor INTO @bookingResourceId, @resourceId, @amount;
-- Iterate
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @amountFree = [dbo].[Fu_GetFreeResources](@startDate, @endDate, @resourceId);
DECLARE @text NVARCHAR(250);
SELECT @text = CONCAT('StartDate = ', @startDate, ', EndDate = ', @endDate, ', ResourceId = ', @resourceId, ', AmountFree = ', @amountFree);
THROW 59002, @text, 1;
-- Some code to insert into BookingResource
-- ...
-- ...
FETCH NEXT FROM @cursor INTO @bookingResourceId, @resourceId, @amount;
END;
CLOSE @cursor;
DEALLOCATE @cursor;
END
在这种情况下,我有一些代码引发错误以向我显示这些值。引发的消息是:
StartDate = Jun 24 2019 12:30PM, EndDate = Jun 24 2019 2:00PM, ResourceId = 3, AmountFree =
最后,功能代码就是这样:
CREATE FUNCTION [dbo].[Fu_GetFreeResources] (
@start_date datetime,
@end_date datetime,
@resource_id bigint
)
RETURNS int
AS
BEGIN
DECLARE @reserved int = 0;
DECLARE @total int = 0;
SELECT
@reserved = SUM(br.amount)
FROM
BookingResource AS br,
Booking AS b
WHERE
br.booking_id = b.id AND
br.resource_id = @resource_id AND
(
(b.start_date < @start_date AND b.end_date > @start_date) OR
(b.start_date < @end_date AND b.end_date > @end_date) OR
(b.start_date >= @start_date AND b.end_date <= @end_date)
);
SELECT
@total = amount
FROM
Resource
WHERE
id = @resource_id;
RETURN @total - @reserved;
END
如果我运行这句话:
DECLARE @start_date DATETIME;
DECLARE @end_date DATETIME;
DECLARE @R INT;
SELECT @start_date = start_date, @end_date = end_date FROM Booking WHERE id = 19;
SELECT @R = dbo.Fu_ObtenerNumRecursosLibres(@start_date, @end_date, 3);
PRINT CONCAT('Start date: ', @start_date);
PRINT CONCAT('End date: ', @end_date);
PRINT CONCAT('Resource Id: ', 3);
PRINT CONCAT(Free resources: ', @R);
我得到以下输出:
Start date: Jun 24 2019 12:30PM
End date: Jun 24 2019 2:00PM
Resource Id: 3
Free resources: 3
但是当我尝试使用相同的资源输入来保留一些空间时:
DECLARE @start_date DATETIME;
DECLARE @end_date DATETIME;
DECLARE @resources BookingResourceType;
SELECT @start_date = start_date, @end_date = end_date FROM Booking WHERE id = 19;
INSERT INTO @resources(bookingResource_id, resource_id, amount) VALUES (NULL, 3, 8);
PRINT CONCAT('Start date: ', @start_date);
PRINT CONCAT('End date: ', @end_date);
PRINT CONCAT('Resource Id: ', 3);
EXEC [dbo].[Pr_SaveBooking] 18, @start_date, @end_date, @resources
我得到了另一个输出:
Start date: Jun 24 2019 12:30PM
End date: Jun 24 2019 2:00PM
Resource Id: 3
Booking done (#57)
Rollback
Mensaje 59002, nivel 16, estado 1, procedimiento Pr_InsertBookingResources, línea 41 [línea de inicio de lote 0]
StartDate = Jun 24 2019 12:30PM, EndDate = Jun 24 2019 2:00PM, ResourceId = 3, AmountFree =
我是使用SQL Server的新手,所以也许这是一个虚拟错误,但我没有找到它。
我正在经历什么?为什么会这样?有什么建议吗?
谢谢
PS :创建数据库
CREATE TYPE [dbo].[BookingResourceType] AS TABLE(
[bookingResource_id] [bigint] NULL,
[resource_id] [bigint] NOT NULL,
[amount] [int] NOT NULL
)
GO
CREATE TABLE [dbo].[Booking](
[id] [bigint] IDENTITY(1,1) NOT NULL,
[user_id] [bigint] NOT NULL,
[room_id] [bigint] NOT NULL,
[observations] [text] NULL,
[start_date] [datetime] NOT NULL,
[end_date] [datetime] NOT NULL,
CONSTRAINT [Booking_PK] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
CREATE TABLE [dbo].[BookingResource](
[id] [bigint] IDENTITY(1,1) NOT NULL,
[resource_id] [bigint] NOT NULL,
[booking_id] [bigint] NOT NULL,
[amount] [int] NOT NULL,
CONSTRAINT [BookingResource_PK] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [BookingResource_UN] UNIQUE NONCLUSTERED
(
[resource_id] ASC,
[booking_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Resource](
[id] [bigint] IDENTITY(1,1) NOT NULL,
[name] [nvarchar](50) NOT NULL,
[amount] [int] NOT NULL,
CONSTRAINT [Resource_PK] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Room](
[id] [bigint] IDENTITY(1,1) NOT NULL,
[name] [nvarchar](100) NOT NULL,
CONSTRAINT [Room_PK] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[User](
[id] [bigint] IDENTITY(1,1) NOT NULL,
[name] [nvarchar](60) NOT NULL,
[code] [nvarchar](50) NOT NULL,
[surname] [nvarchar](60) NOT NULL,
CONSTRAINT [User_PK] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[BookingResource] ADD DEFAULT ((1)) FOR [amount]
GO
ALTER TABLE [dbo].[Resource] ADD DEFAULT ((1)) FOR [amount]
GO
ALTER TABLE [dbo].[Booking] WITH CHECK ADD CONSTRAINT [Booking_Room_FK] FOREIGN KEY([room_id])
REFERENCES [dbo].[Room] ([id])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[Booking] CHECK CONSTRAINT [Booking_Room_FK]
GO
ALTER TABLE [dbo].[Booking] WITH CHECK ADD CONSTRAINT [Booking_User_FK] FOREIGN KEY([user_id])
REFERENCES [dbo].[User] ([id])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[Booking] CHECK CONSTRAINT [Booking_User_FK]
GO
ALTER TABLE [dbo].[BookingResource] WITH CHECK ADD CONSTRAINT [BookingResource_Booking_FK] FOREIGN KEY([booking_id])
REFERENCES [dbo].[Booking] ([id])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[BookingResource] CHECK CONSTRAINT [BookingResource_Booking_FK]
GO
ALTER TABLE [dbo].[BookingResource] WITH CHECK ADD CONSTRAINT [BookingResource_Resource_FK] FOREIGN KEY([resource_id])
REFERENCES [dbo].[Resource] ([id])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[BookingResource] CHECK CONSTRAINT [BookingResource_Resource_FK]
GO
并插入数据:
INSERT INTO Room(id, name) VALUES (1, 'Sala de Juntas');
INSERT INTO Room(id, name) VALUES (2, 'Sala de Reuniones');
INSERT INTO Room(id, name) VALUES (3, 'Sala de Conferencias');
INSERT INTO Room(id, name) VALUES (11, 'Sala de Cursos');
INSERT INTO Room(id, name) VALUES (18, 'Sala de Espera');
INSERT INTO Resource(id, name, amount) VALUES (1, 'Teléfono', 5);
INSERT INTO Resource(id, name, amount) VALUES (2, 'Altavoces', 5);
INSERT INTO Resource(id, name, amount) VALUES (3, 'Proyector', 5);
INSERT INTO Resource(id, name, amount) VALUES (4, 'Micrófono', 5);
INSERT INTO Resource(id, name, amount) VALUES (5, 'Ordenador', 5);
INSERT INTO [dbo].[User](id, name, code, surname) VALUES (1, 'Nombre01', 'Codigo01', 'Apellido01');
INSERT INTO [dbo].[User](id, name, code, surname) VALUES (2, 'Nombre02', 'Codigo02', 'Apellido02');
INSERT INTO [dbo].[User](id, name, code, surname) VALUES (3, 'Nombre03', 'Codigo03', 'Apellido03');
INSERT INTO [dbo].[User](id, name, code, surname) VALUES (4, 'Nombre04', 'Codigo04', 'Apellido04');
INSERT INTO [dbo].[User](id, name, code, surname) VALUES (5, 'Nombre05', 'Codigo05', 'Apellido05');
INSERT INTO [dbo].[User](id, name, code, surname) VALUES (6, 'Nombre06', 'Codigo06', 'Apellido06');
INSERT INTO [dbo].[User](id, name, code, surname) VALUES (7, 'Nombre07', 'Codigo07', 'Apellido07');
INSERT INTO [dbo].[User](id, name, code, surname) VALUES (8, 'Nombre08', 'Codigo08', 'Apellido08');
INSERT INTO [dbo].[User](id, name, code, surname) VALUES (9, 'Nombre09', 'Codigo09', 'Apellido09');
INSERT INTO [dbo].[User](id, name, code, surname) VALUES (10, 'Nombre10', 'Codigo10', 'Apellido10');
INSERT INTO [dbo].[User](id, name, code, surname) VALUES (11, 'Nombre11', 'Codigo11', 'Apellido11');
INSERT INTO [dbo].[User](id, name, code, surname) VALUES (12, 'Nombre12', 'Codigo12', 'Apellido12');
INSERT INTO [dbo].[User](id, name, code, surname) VALUES (13, 'Nombre13', 'Codigo13', 'Apellido13');
INSERT INTO [dbo].[User](id, name, code, surname) VALUES (14, 'Nombre14', 'Codigo14', 'Apellido14');
INSERT INTO [dbo].[User](id, name, code, surname) VALUES (15, 'Nombre15', 'Codigo15', 'Apellido15');
INSERT INTO [dbo].[User](id, name, code, surname) VALUES (16, 'Nombre16', 'Codigo16', 'Apellido16');
INSERT INTO [dbo].[User](id, name, code, surname) VALUES (17, 'Nombre17', 'Codigo17', 'Apellido17');
INSERT INTO [dbo].[User](id, name, code, surname) VALUES (18, 'Nombre18', 'Codigo18', 'Apellido18');
INSERT INTO Booking(id, user_id, room_id, observations, start_date, end_date) VALUES (1, 15, 4, NULL, '2019-06-25 10:30:00.000', '2019-06-25 15:00:00.000');
INSERT INTO Booking(id, user_id, room_id, observations, start_date, end_date) VALUES (2, 1, 4, NULL, '2019-06-28 16:30:00.000', '2019-06-28 18:00:00.000');
INSERT INTO Booking(id, user_id, room_id, observations, start_date, end_date) VALUES (3, 9, 2, NULL, '2019-06-21 10:30:00.000', '2019-06-21 13:00:00.000');
INSERT INTO Booking(id, user_id, room_id, observations, start_date, end_date) VALUES (4, 6, 1, NULL, '2019-06-24 14:00:00.000', '2019-06-24 16:30:00.000');
INSERT INTO Booking(id, user_id, room_id, observations, start_date, end_date) VALUES (5, 11, 5, NULL, '2019-06-25 09:30:00.000', '2019-06-25 11:00:00.000');
INSERT INTO Booking(id, user_id, room_id, observations, start_date, end_date) VALUES (6, 9, 2, NULL, '2019-06-22 15:00:00.000', '2019-06-22 16:30:00.000');
INSERT INTO Booking(id, user_id, room_id, observations, start_date, end_date) VALUES (7, 17, 5, NULL, '2019-06-28 15:30:00.000', '2019-06-28 13:30:00.000');
INSERT INTO Booking(id, user_id, room_id, observations, start_date, end_date) VALUES (8, 11, 2, NULL, '2019-06-30 08:30:00.000', '2019-06-30 13:30:00.000');
INSERT INTO Booking(id, user_id, room_id, observations, start_date, end_date) VALUES (9, 15, 5, NULL, '2019-06-20 13:30:00.000', '2019-06-20 14:00:00.000');
INSERT INTO Booking(id, user_id, room_id, observations, start_date, end_date) VALUES (10, 15, 4, NULL, '2019-06-21 10:00:00.000', '2019-06-21 16:30:00.000');
INSERT INTO Booking(id, user_id, room_id, observations, start_date, end_date) VALUES (11, 17, 2, NULL, '2019-06-24 14:30:00.000', '2019-06-24 15:30:00.000');
INSERT INTO Booking(id, user_id, room_id, observations, start_date, end_date) VALUES (12, 2 3, NULL, '2019-06-29 11:00:00.000', '2019-06-29 13:00:00.000');
INSERT INTO Booking(id, user_id, room_id, observations, start_date, end_date) VALUES (13, 11, 4, NULL, '2019-06-28 13:30:00.000', '2019-06-28 14:00:00.000');
INSERT INTO Booking(id, user_id, room_id, observations, start_date, end_date) VALUES (14, 5, 5, NULL, '2019-06-20 12:00:00.000', '2019-06-20 13:30:00.000');
INSERT INTO Booking(id, user_id, room_id, observations, start_date, end_date) VALUES (15, 8, 3, NULL, '2019-06-30 10:00:00.000', '2019-06-30 18:30:00.000');
INSERT INTO Booking(id, user_id, room_id, observations, start_date, end_date) VALUES (16, 11, 2, NULL, '2019-06-26 12:00:00.000', '2019-06-26 12:30:00.000');
INSERT INTO Booking(id, user_id, room_id, observations, start_date, end_date) VALUES (17, 9, 4, NULL, '2019-06-25 15:30:00.000', '2019-06-25 18:30:00.000');
INSERT INTO Booking(id, user_id, room_id, observations, start_date, end_date) VALUES (18, 9, 3, NULL, '2019-06-20 07:30:00.000', '2019-06-20 14:30:00.000');
INSERT INTO Booking(id, user_id, room_id, observations, start_date, end_date) VALUES (19, 18, 1, NULL, '2019-06-24 12:30:00.000', '2019-06-24 14:00:00.000');
INSERT INTO Booking(id, user_id, room_id, observations, start_date, end_date) VALUES (20, 4, 2, 'Horario raro, comienza a las 9:15 y termina a las 12:20', '2019-06-28 09:15:00.000', '2019-06-28 12:20:00.000');
INSERT INTO Booking(id, user_id, room_id, observations, start_date, end_date) VALUES (21, 1, 2, '', '2019-06-03 10:00:00.000', '2019-06-03 12:30:00.000');
INSERT INTO BookingResource(id, resource_id, booking_id, amount) VALUES (1, 1, 3, 2);
INSERT INTO BookingResource(id, resource_id, booking_id, amount) VALUES (2, 2, 18, 2);
INSERT INTO BookingResource(id, resource_id, booking_id, amount) VALUES (4, 4, 14, 2);
INSERT INTO BookingResource(id, resource_id, booking_id, amount) VALUES (5, 5, 10, 2);
INSERT INTO BookingResource(id, resource_id, booking_id, amount) VALUES (7, 2, 20, 2);
INSERT INTO BookingResource(id, resource_id, booking_id, amount) VALUES (8, 3, 12, 2);
INSERT INTO BookingResource(id, resource_id, booking_id, amount) VALUES (9, 4, 9, 2);
INSERT INTO BookingResource(id, resource_id, booking_id, amount) VALUES (10, 5, 16, 2);
INSERT INTO BookingResource(id, resource_id, booking_id, amount) VALUES (11, 1, 16, 2);
INSERT INTO BookingResource(id, resource_id, booking_id, amount) VALUES (12, 2, 4, 2);
INSERT INTO BookingResource(id, resource_id, booking_id, amount) VALUES (13, 3, 8, 2);
INSERT INTO BookingResource(id, resource_id, booking_id, amount) VALUES (14, 4, 1, 2);
INSERT INTO BookingResource(id, resource_id, booking_id, amount) VALUES (15, 5, 11, 2);
INSERT INTO BookingResource(id, resource_id, booking_id, amount) VALUES (16, 1, 8, 2);
INSERT INTO BookingResource(id, resource_id, booking_id, amount) VALUES (17, 2, 5, 2);
INSERT INTO BookingResource(id, resource_id, booking_id, amount) VALUES (18, 3, 7, 2);
INSERT INTO BookingResource(id, resource_id, booking_id, amount) VALUES (19, 4, 15, 2);
INSERT INTO BookingResource(id, resource_id, booking_id, amount) VALUES (34, 2, 21, 1);
INSERT INTO BookingResource(id, resource_id, booking_id, amount) VALUES (35, 4, 21, 1);
INSERT INTO BookingResource(id, resource_id, booking_id, amount) VALUES (83, 3, 19, 7);
答案 0 :(得分:1)
删除THROW
。
当您在throw
中Pr_InsertBookingResources
时,错误将返回给Pr_SaveBooking
,该错误将其捕获在try-tran-catch块中并回滚所做的所有更改(如会显示“回滚”行)。
请勿使用throw
打印内容。如果要在运行时准确打印,请使用RAISERROR('yourtexthere',0,0) with nowait
。请注意,第一个0是严重性,而严重性0表示它实际上不是错误,并且不会将流传递到catch块。