2009-04-18 87 views
1

以下是我的存儲過程。它包含子查詢有關遊標在SQL中的錯誤

Select StartTime From DrTimings Where DrID = @DrID 

如果此子查詢返回多個值,則出現錯誤。子查詢返回多行。我想在遊標中獲取每個@StartTime和@EndTime。意味着我想「從醫生處取下@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>[email protected] 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>[email protected] and T.StartTime<@EndTime and 
T.SlotId not in 
     (Select A.SlotId from AppointmentSheet A where [email protected]) 

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

     Update @TempSlots 
     Set SlotID = @SlotID, 
       [email protected] 

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

    Select * From @TempSlots 
END 
+0

注意:您也可以將您的第一個BEGIN/END塊更改爲: 選擇@StartTime = StartTime,@EndTime = EndTime從DrTimings其中DrID = @DrID 不需要兩次單獨選擇。 – Brannon 2009-04-18 07:00:15

回答

1

只需添加下一個變量是這樣的:

fetch next from Doctor into @StTime, @EndTime 

光標的select語句應該包含列結束時間:

select StartTime, EndTime 
from TimeList1 
where StartTime>[email protected] and StartTime<@EndTime 
1

雖然遊標是遍歷一個簡單的方法結果集,他們是而不是因爲性能影響而推薦。

如果我知道你的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的最新值,那麼甚至不需要迭代。

+0

這是我的TimeSlot1結構 SlotID int, StartTime datetime EndTime datetime – user42348 2009-04-18 07:48:26