如何在sql server 2008中替换游标

时间:2011-04-02 06:37:16

标签: sql-server tsql sql-server-2008

在过去的几年里,我在c#中付出了很多努力并且离开了sql server。 我的sql技能可能会更好。 我知道游标很慢等等......我已经把一个我在工作中遇到相当多的点头示例放在一起。

我需要从一个平面表“Customer”中迁移数据

进入许多表

“CustomerAddress”“CustomerPhone”等。

如果你被分配了这个任务,你怎么能不使用游标呢?

要转换的光标

            BEGIN TRANSACTION


            DECLARE @CustomerID int,
                    @Name nvarchar(50),
                    @Surname nvarchar(50),
                    @DateOfBirth datetime,
                    @Address nvarchar(200),
                    @City nvarchar(50),
                    @County nvarchar(50),
                    @Country nvarchar(50),
                    @HomePhone nvarchar(20)


            DECLARE OldCustomerCursor CURSOR FAST_FORWARD
            FOR
            SELECT CustomerID,Name,Surname,DateOfBirth,Address,City,County,Country,HomePhone
            FROM OldCustomer

            OPEN OldCustomerCursor

            FETCH NEXT FROM OldCustomerCursor INTO  @CustomerID,
                                                    @Name ,
                                                    @Surname ,
                                                    @DateOfBirth ,
                                                    @Address ,
                                                    @City ,
                                                    @County ,
                                                    @Country ,
                                                    @HomePhone

            WHILE @@FETCH_STATUS = 0
            BEGIN


                INSERT [dbo].[Customer] ([CustomerID], [Name], [Surname], [DateOfBirth])
                VALUES(@CustomerID,@Name,@Surname,@DateOfBirth)  

                INSERT [CustomerAddress]([AddressID],[CustomerID],[Country],[Address],[City],[County])
                VALUES(@Count,@CustomerID,@County,@Address,@City,@Country)

                INSERT [dbo].[CustomerTelephone]([TelephoneID],[CustomerID],[Number])
                VALUES(@Count,@CustomerID, @HomePhone)

              FETCH NEXT FROM OldCustomerCursor INTO @CustomerID,
                                                 @Name ,
                                                 @Surname ,
                                                 @DateOfBirth ,
                                                 @Address ,
                                                 @City ,
                                                 @County ,
                                                 @Country ,
                                                 @HomePhone
            END

            CLOSE OldCustomerCursor
            DEALLOCATE OldCustomerCursor

            SELECT  * FROM    Customer
            SELECT  * FROM    CustomerAddress
            SELECT  * FROM    CustomerTelephone
            ROLLBACK TRANSACTION

感谢您提供有关如何更换光标的任何建议

5 个答案:

答案 0 :(得分:2)

INSERT INTO tablename (column1, column2 ...)
SELECT column1, column2...
FROM mastertable

为每组列和表执行此操作。

答案 1 :(得分:1)

我认为没有理由使用游标,你可以像这样尝试

SELECT CustomerID,Name,Surname,DateOfBirth,Address,City,County,Country,HomePhone
FROM OldCustomer

INSERT [dbo].[Customer] ([CustomerID], [Name], [Surname], [DateOfBirth])
SELCT CustomerID,Name,Surname,DateOfBirth
FROM  OldCustomer

INSERT [CustomerAddress]([AddressID],[CustomerID],[Country],[Address],[City],[County])
SELECT Count,CustomerID,County,Address,City,Country 
FROM  OldCustomer

INSERT [dbo].[CustomerTelephone]([TelephoneID],[CustomerID],[Number])
SELECT Count,CustomerID, HomePhone
FROM OldCustomer

答案 2 :(得分:0)

建议您阅读此内容,了解如何避免使用游标。 http://wiki.lessthandot.com/index.php/Cursors_and_How_to_Avoid_Them

另外,如果系统正在生成GUID,请查看OUTPUT子句以获取GUID(以及自然键,以便您知道要将哪个记录与之关联)。

答案 3 :(得分:0)

我有一个正在进行索赔裁决的存储过程:通过游标查看每个索赔,然后根据索赔类型填充必要的表来处理它。它非常慢 - 需要几个小时才能运行。我通过使用基于集合的SQL处理每组类似的声明来优化它。它跑了几秒钟。

通常,人们认为他们需要游标来代表一系列条件:

DECLARE UserCursor CURSOR
FOR SELECT UserType, UserID FROM Users
OPEN UserCursor
FETCH NEXT whatever
CASE UserType 
  WHEN 'Employee' THEN do something
  WHEN 'Manager' THEN do another thing
  WHEN 'Owner' THEN do get coffee
  WHEN 'Customer' THEN take money
END
CLOSE CURSOR

或类似的东西。

实际上,你可以这样做:

SELECT UserType, UserID
FROM Users
WHERE UserType = 'Employee'
  do something

SELECT UserType, UserID
FROM Users
WHERE UserType = 'Manager'
  do another thing

这对程序程序员来说看起来更糟糕,但它所以更快,甚至都不好笑。不要考虑基于行的处理,考虑基于集合的处理。这就是数据库的用途。

答案 4 :(得分:0)

您可以使用表变量而不是游标

--declare table variable 
declare @tblCustomersVar table
(
    CustomerID int,
    Name nvarchar(50),
    Surname nvarchar(50),
    DateOfBirth datetime,
    Address nvarchar(200),
    City nvarchar(50),
    County nvarchar(50),
    Country nvarchar(50),
    HomePhone nvarchar(20)
)
insert into @tblCustomersVar
 SELECT CustomerID,Name,Surname,DateOfBirth,Address,City,County,Country,HomePhone
 FROM OldCustomer

 --declare @counter variable
 declare @counter int
 declare @rowCount int
 set @counter=1
 set @rowCount=(select COUNT(*) from @tblCustomersVar)

 while(@counter<=@rowCount)
  Begin
    --process here

  --increment
     set @counter=@counter+1
  End