【问题标题】:Using a while loop with SQL cursors?使用带有 SQL 游标的 while 循环?
【发布时间】:2023-03-10 15:50:02
【问题描述】:

我正在创建一个 sql 脚本,我有 2 个游标来循环数据,一个表游标和一个公司游标。 我在使用 while 循环将数据复制到架构中将公司光标放在一起时遇到问题 我需要使用 If 语句回答以下问题

该表是否有 companyID 列?检查公司 ID 的 if 语句 如果是,则根据光标中的 companyID 复制数据

我声明了一个@firstLoop

这是我的光标特定代码

DECLARE @firstLoop BIT
SET @firstLoop = true

----------- Cursor specific code starts here ------------
-- company cursor
declare copyCompanyDataCursor CURSOR fast_forward FOR
SELECT ID from #CompanyIDs;

open copyCompanyDataCursor
fetch next from copyCompanyDataCursor into @Company_Id;

WHILE @@FETCH_STATUS = 0
    BEGIN

        declare @processorder int;
        declare @tablename varchar(500);
        -- table cursor

        declare copyTableDataCursor CURSOR fast_forward FOR
        SELECT processorder,tablename from #TableList4 order by processorder;

        open copyTableDataCursor
        fetch next from copyTableDataCursor into @processorder, @tablename;

        while @@FETCH_STATUS = 0
        BEGIN
            SET IDENTITY_INSERT [c365online_script1.dbo.tCompany] OFF

            -- Does the table have a companyID column? if statement checking for company id

            -- if yes then copy data based on companyID in cursor

            -- if no check if this is the first time through company loop and copy all data
            -- if @firstloop company exists look at information schema

                    -- insert into c365online_script1.dbo.tCompany(selec
                    EXEC('INSERT ' + @Destination_Database_Name + '.dbo.' + @tablename + ' SELECT * FROM ' + @Source_Database_Name + '.dbo.' + @tablename + ')')

                    -- company logic


            SET IDENTITY_INSERT [c365online_script1.dbo.tCompany] ON

            FETCH NEXT FROM copyTableDataCursor into @processorder,@tablename;
        END

        close copyTableDataCursor;
        Deallocate copyTableDataCursor;

--INSERT INTO c365online_script1.dbo.tCompany
--SELECT *
--FROM production2.tCompany
--WHERE ISNULL(CompanyID, 0) = 0  -- copy all data where id is equal to zero
--@Destination_Database_Name

--      
        --EXEC(INSERT  + @Destination_Database_Name + '.dbo.' + @tablename + ' SELECT * FROM ' + @Source_Database_Name + '.dbo.' + @tablename + ' WHERE ' + @Source_Database_Name + '.dbo.' + @tablename + '.CompanyID = ' + @Company_Id + ')'      
        SET @firstLoop = false;
        FETCH NEXT FROM copyCompanyDataCursor into @Company_Id;
    END
CLOSE copyCompanyDataCursor;
DEALLOCATE copyCompanyDataCursor;

【问题讨论】:

  • 呃,这一切的意义何在?如果您实际上是在尝试复制模式,则几乎可以肯定有内置选项...
  • 目的是通过生成一个脚本来减小数据库的大小,您可以使用该脚本通过仅选择给定时间需要的少数公司来生成缩小的数据库。架构已经复制到一个空数据库中,我现在需要填充它。
  • ...如果您不复制所有表,我会将为此考虑的相关表诚实地放入他们自己的模式中。默认情况下应该有可生成的脚本来复制模式表。并且可能用于表格内容......也许。 为什么您要以这种方式复制数据库?请注意,这实际上不会减少主数据库的大小,因为您仍然拥有所有原始数据。
  • 我被设置了这个任务,并被明确告知要这样做
  • 数据库会更小,因为您会在脚本开头指定公司 ID,并且不会创建整个数据库。

标签: sql tsql if-statement while-loop ssms


【解决方案1】:

我建议你将两个 CURSORS 都替换为 while 循环。

SQL Server 中的 CURSORS 成本性能非常糟糕,而不是用带有 While 循环的临时表替换它们肯定会提高性能,并且您必须编写更简单的编码类型。

有关 SQL Server 的文章,请查看以下链接 SQL Server real time articles

【讨论】:

  • 感谢您的建议,虽然我还没有对使用游标做出判断,但我已经被告知要使用它们,但会建议使用 while 循环。
  • 呃,从技术上讲,他已经在使用while 循环来驱动游标...您是对的,与实际的基于集合的处理相比,游标往往会降低性能...但是,当前的过程似乎需要某种形式的 RBAR 处理,这可能会比使用游标更多密集。此外,该链接中似乎没有提到游标......以及其他问题
  • 我不同意,因为这完全取决于场景。将数据加载到tempdb 并不总是一个好主意。所以,你不能概括答案。它总是取决于一个场景,他们应该测试这两种方法并选择一种在他们的情况下表现更好的方法。
猜你喜欢
  • 1970-01-01
  • 2019-05-17
  • 2020-08-26
  • 2020-11-27
  • 2018-01-12
  • 2021-07-31
  • 2013-03-25
  • 1970-01-01
  • 2015-03-11
相关资源
最近更新 更多