当我直接执行一个函数并将其用于过程中时,为什么会有不同的结果?

时间:2019-06-19 11:33:20

标签: sql sql-server

我正在做一个房间预定服务,除了预定房间之外,还将为会议保留一些必要的资源。

我有一个存储过程,该过程执行一些初步检查,完成后便进行房间预订(在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);

1 个答案:

答案 0 :(得分:1)

删除THROW

当您在throwPr_InsertBookingResources时,错误将返回给Pr_SaveBooking,该错误将其捕获在try-tran-catch块中并回滚所做的所有更改(如会显示“回滚”行)。

请勿使用throw打印内容。如果要在运行时准确打印,请使用RAISERROR('yourtexthere',0,0) with nowait。请注意,第一个0是严重性,而严重性0表示它实际上不是错误,并且不会将流传递到catch块。