SQL 中关于游标的错误

发布于 2024-07-17 11:36:45 字数 1799 浏览 7 评论 0原文

以下是我的存储过程。 它包含一个子查询,

 Select StartTime From DrTimings Where DrID = @DrID 

如果此子查询返回多个值,我会收到错误。 子查询返回多行。 我想获取光标中的每个@StartTime 和@EndTime。 意味着我想“从 Doctor 获取下一个数据到 @StTime 和 @EndTime”

我可以在游标中使用两个参数吗?

ALTER PROCEDURE [dbo].SP_AFK_GetSlotsByDate
    @DrID int,
    @AppointmentDate Datetime 
AS
BEGIN

Declare @StartTime Datetime
Declare @EndTime Datetime
BEGIN
    SET @StartTime = (Select StartTime From DrTimings Where DrID = @DrID)
    SET @EndTime =  (Select EndTime From DrTimings Where DrID = @DrID)
END

DECLARE Doctor CURSOR FOR

Select StartTime  from  TimeList1 where StartTime>=@StartTime and StartTime<@EndTime

Declare @StTime datetime
Declare @SlotID int
Declare @AppointmentTime datetime

Declare @TempSlots Table (SlotID int , AppointmentTime datetime null) 


Insert into
@TempSlots
(
SlotID ,
AppointmentTime
)
values(
0,
Getdate()
)

open Doctor
    fetch next from Doctor into @StTime
        while @@fetch_status = 0
            Begin

Select  @SlotID= T.SlotId from TimeList1 T
where T.StartTime>=@StartTime and T.StartTime<@EndTime and
T.SlotId not in 
        (Select A.SlotId from AppointmentSheet A where A.AppointmentDate=@AppointmentDate)

Select @AppointmentTime = Convert(varchar,right(T.StartTime,7),131)+' - '+ Convert(varchar,right(T.EndTime,7),131) 
from TimeList1 T
where T.StartTime>=@StartTime and T.StartTime<@EndTime and
T.SlotId not in 
        (Select A.SlotId from AppointmentSheet A where A.AppointmentDate=@AppointmentDate)

        Update @TempSlots
        Set SlotID  = @SlotID,
                AppointmentTime=@AppointmentTime

    fetch next from Doctor into @StTime
           end
    close Doctor
    deallocate Doctor

    Select * From @TempSlots
END 

following is my stored procedure. It contains a subquery

 Select StartTime From DrTimings Where DrID = @DrID 

If this subquery returns more than one value, I get an error. Subquery returns multiple rows. I want to get each @StartTime and @EndTime in cursor. Means I want to "fetch next from Doctor into @StTime and @EndTime"

Can I use two parameters in a cursor?

ALTER PROCEDURE [dbo].SP_AFK_GetSlotsByDate
    @DrID int,
    @AppointmentDate Datetime 
AS
BEGIN

Declare @StartTime Datetime
Declare @EndTime Datetime
BEGIN
    SET @StartTime = (Select StartTime From DrTimings Where DrID = @DrID)
    SET @EndTime =  (Select EndTime From DrTimings Where DrID = @DrID)
END

DECLARE Doctor CURSOR FOR

Select StartTime  from  TimeList1 where StartTime>=@StartTime and StartTime<@EndTime

Declare @StTime datetime
Declare @SlotID int
Declare @AppointmentTime datetime

Declare @TempSlots Table (SlotID int , AppointmentTime datetime null) 


Insert into
@TempSlots
(
SlotID ,
AppointmentTime
)
values(
0,
Getdate()
)

open Doctor
    fetch next from Doctor into @StTime
        while @@fetch_status = 0
            Begin

Select  @SlotID= T.SlotId from TimeList1 T
where T.StartTime>=@StartTime and T.StartTime<@EndTime and
T.SlotId not in 
        (Select A.SlotId from AppointmentSheet A where A.AppointmentDate=@AppointmentDate)

Select @AppointmentTime = Convert(varchar,right(T.StartTime,7),131)+' - '+ Convert(varchar,right(T.EndTime,7),131) 
from TimeList1 T
where T.StartTime>=@StartTime and T.StartTime<@EndTime and
T.SlotId not in 
        (Select A.SlotId from AppointmentSheet A where A.AppointmentDate=@AppointmentDate)

        Update @TempSlots
        Set SlotID  = @SlotID,
                AppointmentTime=@AppointmentTime

    fetch next from Doctor into @StTime
           end
    close Doctor
    deallocate Doctor

    Select * From @TempSlots
END 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

两人的回忆 2024-07-24 11:36:45

只需这样添加下一个变量:

fetch next from Doctor into @StTime, @EndTime

光标的 select 语句应包含 EndTime 列:

select StartTime, EndTime 
from   TimeList1 
where  StartTime>=@StartTime and StartTime<@EndTime

Just add the next variable this way:

fetch next from Doctor into @StTime, @EndTime

The select statement of your cursor should contain the column EndTime:

select StartTime, EndTime 
from   TimeList1 
where  StartTime>=@StartTime and StartTime<@EndTime
奢华的一滴泪 2024-07-24 11:36:45

虽然游标是迭代结果集的一种简单方法,但由于性能影响,推荐使用它们。

如果我知道您的 TimeList1 表的结构及其与 DrTimings 表的关系,我会推荐一个使用游标的版本。

但是,在审查了您的 T-SQL 后,我决定为您提供一个更新版本,该版本可以减少冗余并使用 JOINS 而不是子查询:

ALTER PROCEDURE [dbo].SP_AFK_GetSlotsByDate
(
    @DrID int,
    @AppointmentDate DateTime 
)
AS

DECLARE 
    @StartTime DateTime,
    @EndTime DateTime,
    @SlotID int,
    @AppointmentTime DateTime;

-- Retrieve the initial values for StartTime and EndTime
-- These values get overwritten by the cursor (?)
SELECT 
    @StartTime = StartTime,
    @EndTime = EndTime
FROM
    DrTimings
WHERE
    DrID = @DrID;


DECLARE @TempSlots TABLE
(
    SlotID int, 
    AppointmentTime datetime NULL
); 

-- Set default values
INSERT @TempSlots (SlotID,AppointmentTime)
VALUES (0, GETDATE());


DECLARE Doctor CURSOR FOR
SELECT 
    StartTime,
    EndTime  
FROM  
    TimeList1 
where 
    StartTime >= @StartTime AND 
    StartTime < @EndTime;

OPEN Doctor
FETCH NEXT FROM Doctor INTO @StartTime,@EndTime
WHILE @@FETCH_STATUS = 0
    BEGIN
        SELECT
            @SlotID = T.SlotId, 
            @AppointmentTime = CONVERT(varchar,RIGHT(T.StartTime,7),131)
                               + ' - ' + CONVERT(varchar,RIGHT(T.EndTime,7),131) 
        FROM 
            TimeList1 T
            LEFT JOIN AppointmentSheet A ON T.SlotId = A.SlotId
        WHERE 
            T.StartTime >= @StartTime AND 
            T.StartTime < @EndTime AND
            A.AppointmentDate = @AppointmentDate AND
            A.SlotId IS NULL;

        -- This table will always be updated to contain the latest values
        -- it will contain only one row
        UPDATE 
            @TempSlots
        SET
            SlotID  = @SlotID,
            AppointmentTime = @AppointmentTime;

        FETCH NEXT FROM Doctor INTO @StartTime,@EndTime
    END

CLOSE Doctor
DEALLOCATE Doctor

-- Return results
SELECT 
    SlotId,
    AppointmentTime
FROM 
    @TempSlots;

更新:如果目的是获取 SlotId 和 AppointmentTime 的最新值,那么甚至不需要迭代。

While cursors are an easy way to iterate through a result set, they are not recommended because of performance implications.

If I knew the structure of your TimeList1 table and it's relation to the DrTimings table, I would recommend a version that does not use cursors.

However, after reviewing your T-SQL, I decided to provide you with an updated version that reduces redundancies and uses JOINS instead of subqueries:

ALTER PROCEDURE [dbo].SP_AFK_GetSlotsByDate
(
    @DrID int,
    @AppointmentDate DateTime 
)
AS

DECLARE 
    @StartTime DateTime,
    @EndTime DateTime,
    @SlotID int,
    @AppointmentTime DateTime;

-- Retrieve the initial values for StartTime and EndTime
-- These values get overwritten by the cursor (?)
SELECT 
    @StartTime = StartTime,
    @EndTime = EndTime
FROM
    DrTimings
WHERE
    DrID = @DrID;


DECLARE @TempSlots TABLE
(
    SlotID int, 
    AppointmentTime datetime NULL
); 

-- Set default values
INSERT @TempSlots (SlotID,AppointmentTime)
VALUES (0, GETDATE());


DECLARE Doctor CURSOR FOR
SELECT 
    StartTime,
    EndTime  
FROM  
    TimeList1 
where 
    StartTime >= @StartTime AND 
    StartTime < @EndTime;

OPEN Doctor
FETCH NEXT FROM Doctor INTO @StartTime,@EndTime
WHILE @@FETCH_STATUS = 0
    BEGIN
        SELECT
            @SlotID = T.SlotId, 
            @AppointmentTime = CONVERT(varchar,RIGHT(T.StartTime,7),131)
                               + ' - ' + CONVERT(varchar,RIGHT(T.EndTime,7),131) 
        FROM 
            TimeList1 T
            LEFT JOIN AppointmentSheet A ON T.SlotId = A.SlotId
        WHERE 
            T.StartTime >= @StartTime AND 
            T.StartTime < @EndTime AND
            A.AppointmentDate = @AppointmentDate AND
            A.SlotId IS NULL;

        -- This table will always be updated to contain the latest values
        -- it will contain only one row
        UPDATE 
            @TempSlots
        SET
            SlotID  = @SlotID,
            AppointmentTime = @AppointmentTime;

        FETCH NEXT FROM Doctor INTO @StartTime,@EndTime
    END

CLOSE Doctor
DEALLOCATE Doctor

-- Return results
SELECT 
    SlotId,
    AppointmentTime
FROM 
    @TempSlots;

Update: If the intent is to obtain the latest values for SlotId and AppointmentTime, then iteration is not even needed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文