游标在我的存储过程中花时间?

时间:2013-09-20 17:20:38

标签: sql-server tsql stored-procedures sql-server-2008-r2 cursor

我在SQL Server 2008 r2下的存储过程中有两个游标。他们在执行存储过程时会消磨我的时间吗? 我有2张桌子

##TEMP

CatalogID    Value
34567         80
34848         100
34725         40


##Temp1

   Name    Percentage
     A       25
     B       25
     C       25
     D       25

通过使用两个临时表iam将数据插入到目录表中并删除输入的catalogid和值。

catalogtable



 CatalogID    name    value

  34567          A      20
  34567          B      20
  34567          C      20
  34567          D      20
  34848          A      25
  34848          B      25
  34848          C      25
  34848          D      25
  34725          A      10
  34725          B      10
  34725          C      10
  34725          D      10

我的光标是

DECLARE Cur_Rotation CURSOR
FOR 
                  SELECT CatalogId,Value FROM ##TEMP
                   DECLARE  @CatalogId INT
                   DECLARE @Value [decimal](5, 2)
                   OPEN Cur_Rotation
                   FETCH NEXT FROM Cur_Rotation INTO @CatalogId,@Value
                   While @@FETCH_STATUS = 0
BEGIN
           DECLARE Cur_Inner CURSOR
           FOR
                              SELECT Name,Percentage FROM ##Temp1
                              DECLARE @Name VARCHAR(50)
                              DECLARE @Percentage [decimal](5, 2)
                              OPEN Cur_Inner
                              FETCH NEXT FROM Cur_Inner   INTO @Name,@Percentage
                              While @@FETCH_STATUS = 0
BEGIN

                             DECLARE @Value1 [decimal](5, 2) 

                             SET @Value=@Value1*(@Percentage/100.00)
               DELETE FROM  CatalogDetails WHERE CatalogId=@CatalogId  and name=@name
                INSERT INTO CatalogDetails (name,RDDRotPcent,CatalogId)
                                VALUES (@name,@Value1,@CatalogId) 
        FETCH NEXT FROM Cur_Inner  INTO @Name,@Percentage
END
CLOSE Cur_Inner
DEALLOCATE Cur_Inner 
                        FETCH NEXT FROM Cur_Rotation INTO @CatalogId,@Value
END                        

CLOSE Cur_Rotation
DEALLOCATE Cur_Rotation
END

是否有机会使用任何逻辑来跳过游标。当时我的查询执行需要花费数千次.CatalogID将成千上万。所以有机会更改我的SCRIPT以避免游标。

3 个答案:

答案 0 :(得分:5)

在您的情况下,您可以在没有游标的情况下执行此操作,甚至无需递归查询:

insert into catalogtable (CatalogID, name, value)
select
    t.CatalogID,
    t1.name,
    t.Value * t1.Percentage / 100.00
from #TEMP as t
    cross join #TEMP1 as t1

<强> sql fiddle demo

答案 1 :(得分:2)

这是有用的,并且我相信你的整个问题

--Prepare data

DECLARE @Temp1 AS TABLE
(
    CatalogId INT,
    VALUE DECIMAL(19,5)
    )

    INSERT INTO @Temp1 SELECT 34567, 80
    INSERT INTO @Temp1 SELECT 34848, 100
    INSERT INTO @Temp1 SELECT 34725, 40


DECLARE @CatalogDetails AS TABLE
(Id INT PRIMARY KEY IDENTITY(1,1), NAME NVARCHAR(100), RDDRotPcent DECIMAL(19,5), CatalogId INT)

INSERT INTO @CatalogDetails SELECT 'A', .99, 12345
INSERT INTO @CatalogDetails SELECT 'B', .99, 34567


DECLARE @Temp2 AS TABLE
( NAME NVARCHAR(100),
 Percentage DECIMAL(19,5))

 INSERT INTO @Temp2 SELECT 'A', .25
 INSERT INTO @Temp2 SELECT 'B', .25
 INSERT INTO @Temp2 SELECT 'C', .25
 INSERT INTO @Temp2 SELECT 'D', .25


 DECLARE @Catalog AS TABLE
 (CatalogId INT, NAME NVARCHAR(100), VALUE DECIMAL(19,5))
--Fill Catalog with new Data
 INSERT INTO @Catalog

         SELECT CatalogId, NAME, Value * Percentage FROM @Temp1, @Temp2

--Delete Old Values
         DELETE FROM @CatalogDetails WHERE Id IN (SELECT Id FROM @CatalogDetails CD Inner JOIN @Catalog C ON CD.CatalogId = C.CatalogId AND CD.Name = C.NAME)

--Insert New Values

         INSERT INTO @CatalogDetails SELECT Name, Value, CatalogId FROM @Catalog

--View End Result
         SELECT * FROM @CatalogDetails

答案 2 :(得分:1)

不太确定它有多大帮助。但你可以尝试这样的东西来避免光标: -

DECLARE @number_rows     int
DECLARE @count           int
DECLARE @selected     int

DECLARE @table1 TABLE (Id int not null primary key identity(1,1), col1 int )  
INSERT into @table1 (col1) SELECT col1 FROM table2
SET @number_rows=@@ROWCOUNT

SET @count=0
WHILE @count<@number_rows     
BEGIN
    SET @count=@count+1
    SELECT 
        @selected=col1
        FROM @table1
        WHERE Id=@count

    --do your stuff here--

END