光标逻辑错误

时间:2013-10-07 13:14:30

标签: sql-server

我写了这个SP来存储来自两个表的数据,其中第二个表包含sectionID 我想将学生分发到他们的部分

ALTER PROC [dbo].[StudentDistribution] -- '6,7,8,9,10','1,2',1,1   
(
@pUserID varchar(8000),
@pSectionID varchar(8000),
@pClassID int,
@pModifiedBy int
)
as




DECLARE @Cntr int   
set @Cntr = (select count(*) from split(@pUserID,','))
select sum(Capacity) from SectionsClasses where ClassID=@pClassID and SectionID in (select vItem from split(@pSectionID,','))

DECLARE FetchStudent Cursor for
select vItem from split(@pUserID,',')

DECLARE @vUserID  int
DECLARE @vSecID int
DECLARE @vOut_Status int
DECLARE @vInner_Status int

        Open FetchStudent
        Fetch NEXT From FetchStudent into @vUserID
        set @vOut_Status= @@FETCH_STATUS 
        WHILE @vOut_Status = 0 

            begin 
            DECLARE FetchSection Cursor for
            select vItem from split(@pSectionID,',')

                OPEN FetchSection
                    Fetch NEXT From FetchSection into @vSecID
                    set @vInner_Status= @@FETCH_STATUS
                    WHILE @vInner_Status = 0 
                    begin

                    print(@vUserID)
                    print(@vSecID)


                    --IF @cntr <= 0
                    --  break
                    --else
                    --  set @Cntr=@Cntr-1



                    Fetch NEXT From FetchStudent into @vUserID
                    set @vOut_Status= @@FETCH_STATUS

                    Fetch NEXT From FetchSection into @vSecID
                    set @vInner_Status= @@FETCH_STATUS




                    END
                    Close FetchSection
                    Deallocate FetchSection

            --IF @cntr <= 0
            --          break
            --      else
            --          set @Cntr=@Cntr-1
            Fetch NEXT From FetchStudent into @vUserID

            END
    Close FetchStudent
    Deallocate FetchStudent

我需要得到这个结果

6  1
7  2
8  1
9  2
10 1

但我得到的是

6  1
7  2
9  1
10 2

任何人都可以找出问题所在吗?

2 个答案:

答案 0 :(得分:0)

这是答案

 ALTER PROC [dbo].[StudentDistribution] --'6,7,8,9,10,11,12,13','1',3,1   
(
@pUserID varchar(8000),
@pSectionID varchar(8000),
@pClassID int,
@pModifiedBy int    
)
as



DECLARE @vCntr int  
DECLARE @vCapacity int 

set @vCntr = (select count(*) from split(@pUserID ,','))
select  @vCapacity = sum(Capacity) from SectionsClasses where ClassID=@pClassID and SectionID in (select vItem from split(@pSectionID,','))

    if @vCntr >  @vCapacity
    BEGIN
        print('Operation cannot complete; the number of student exceeds capacity')
            Return
    END

DECLARE FetchStudent Cursor  SCROLL for
select vItem from split(@pUserID,',')

DECLARE @vUserID  int
DECLARE @vSecID int
DECLARE @vOut_Status int
DECLARE @vInner_Status int

        Open FetchStudent
        Fetch NEXT From FetchStudent into @vUserID
        set @vOut_Status= @@FETCH_STATUS 
        WHILE (@vOut_Status = 0 )

            begin 
            DECLARE FetchSection Cursor  SCROLL for
            select vItem from split(@pSectionID,',')

                OPEN FetchSection
                    Fetch NEXT From FetchSection into @vSecID
                    set @vInner_Status= @@FETCH_STATUS
                    WHILE (@vInner_Status = 0 )
                    BEGIN

                    print(@vUserID)
                    print(@vSecID)


                    Fetch NEXT From FetchSection into @vSecID
                    set @vInner_Status= @@FETCH_STATUS
                    --IF @vInner_Status = -1
                    --      BREAK
                    Fetch NEXT From FetchStudent into @vUserID
                    set @vOut_Status= @@FETCH_STATUS 
                        IF @vOut_Status = -1
                            BREAK


                    END

                    Close FetchSection
                    Deallocate FetchSection



            IF @vInner_Status =-1
            Fetch PRIOR From FetchStudent into @vUserID

            Fetch NEXT From FetchStudent into @vUserID
            set @vOut_Status= @@FETCH_STATUS

            END
    Close FetchStudent
    Deallocate FetchStudent

答案 1 :(得分:0)

作为光标的替代方案,我们需要考虑以下事项:

WITH sections AS (
  SELECT
    x.ID,
    RN = ROW_NUMBER() OVER (ORDER BY x.ID)
  FROM dbo.split(@pSectionID, ',') AS f
  CROSS APPLY (SELECT CAST(f.vItem AS int)) AS x (ID)
),
users AS (
  SELECT
    x.ID,
    SectionRN = NTILE((SELECT COUNT(*) FROM sections)) OVER (ORDER BY x.ID)
  FROM dbo.split(@pUserID, ',') AS f
  CROSS APPLY (SELECT CAST(f.vItem AS int)) AS x (ID)
)
SELECT
  UserID    = u.ID,
  SectionID = s.ID
FROM users AS u
INNER JOIN sections AS s ON u.SectionRN = s.RN
;

对于@pUserID '6,7,8,9,10'pSectionID'1,2',上述内容将返回如下结果集:

UserID  SectionID
------  ---------
6       1
7       1
8       1
9       2
10      2

如果你坚持这样的结果:

UserID  SectionID
------  ---------
6       1
7       2
8       1
9       2
10      1

SectionRN中的users计算更改为:

SectionRN = (ROW_NUMBER() OVER (ORDER BY x.ID) - 1) % (SELECT COUNT(*) FROM sections) + 1

有用的阅读: