【问题标题】:Cursors Or While Loop what will be a good option to work on 6,00,000+ rows data游标或 While 循环什么是处理 6,00,000 多行数据的好选择
【发布时间】:2017-08-25 19:03:03
【问题描述】:

我有一个 table_A,我从 .csv 文件导入数据。我想将 table_A 中的一些列与 table_B 进行比较,并相应地将数据插入到表中并将状态更新为 table_A。 我应该使用While循环或光标..请建议

DECLARE @A_2 VARCHAR(10), @A_3 VARCHAR(50), @A_4 VARCHAR(100)
    DECLARE db_cursor CURSOR FOR  
    SELECT A_2, A_3, A_4 FROM Temp_table

OPEN db_cursor  
    FETCH NEXT FROM db_cursor   
    INTO @A_2, @A_3, @A_4 
    WHILE @@FETCH_STATUS = 0  
    BEGIN  
    If @A_2 <> (SELECT C_2 FROM Table_C where C_2= @A_2)
        UPDATE Temp_table SET [Status]='Not Exits in Table_C'
    ELSE BEGIN
       IF @A_3=(Select B_3 from Table_B where B_3=@A_3) AND @A_2=(SELECT B_2              FROM Table_B where B_2= @A_2)
       UPDATE Temp_table SET [Status]='Duplicate Row, Already Exists'
       ELSE 
            IF (@A_4 <>'B_4 '+'B_5')
            UPDATE Temp_table SET [Status]=' Format is not accepted '
            ELSE
            INSERT INTO Table_B(B_2, B_3, B_4) VALUES(@A_2, @A_3, @A_4)

    END
  CLOSE db_cursor  DEALLOCATE db_cursor    
  FETCH NEXT FROM db_cursor  INTO @A_2, @A_3, @A_4
    END   

这里的 Temp_table 是我将从 .csv 文件导入数据的表,并且将使用 Table_B、Table_C 和 Temp_Table 的列进行比较 这会是正确的做法吗?

【问题讨论】:

  • 关系数据库的重大转变是摆脱程序性思维 - while 和 curosrs - 并开始考虑集合。 SQL 擅长比较大量数据并对其进行操作。拥抱 SQL!
  • 都不行,改用基于集合的查询。
  • 位开放式,还有其他选项可用,取决于性能,您可以使用直接查询(不需要循环或游标,基于集合的方法会更好),或使用 SSIS 作为选项如果数据集太大/性能是一个问题,则可以进行更线性的思考
  • 如果您希望共享一些示例数据,您打算如何比较它们,以及您打算将什么结果插入到新表中,我们可以帮助编写该 SQL。很可能所有这三个步骤都是 1 个 SQL 语句。

标签: sql sql-server sql-server-2012-web


【解决方案1】:

我对性能不太熟悉,但我不建议使用 while 循环,因为它真的很慢。我会做一些类似的事情:

UPDATE table1
SET table1.column1 = table2.column1,
    table1.column2 = table2.column2
WHERE (do a select statement or column comparison)

这只是一般指南,我希望它可以帮助您入门。否则,您将不得不更加具体。

更新和比较参考:

How do I UPDATE from a SELECT in SQL Server?

Microsoft UPDATE

【讨论】:

    【解决方案2】:

    两者都没有。如果您使用 SQL,第一步是摆脱程序性思维,转向基于集合的思维。

    要执行您想要执行的操作,请使用MERGEhttps://docs.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql

    设置

    IF OBJECT_ID('tempdb..#table_A') IS NOT NULL
      DROP TABLE #table_A
    
    CREATE TABLE #table_A (col1 int, col2 int, colX int, checkme bit DEFAULT 0) ;
    INSERT INTO #table_A (col1, col2, colX)
    VALUES 
          (1,1,1)
        , (2,2,2)
        , (3,3,3)
        , (4,4,4)
    ;
    
    IF OBJECT_ID('tempdb..#table_B') IS NOT NULL
      DROP TABLE #table_B
    
    CREATE TABLE #table_B (col1 int, col2 int, colX int) ;
    INSERT INTO #table_B (col1, col2, colX)
    VALUES 
          (0,0,1)
        , (0,0,2)
    ;
    

    之前

    SELECT * FROM #table_A ;     
    SELECT * FROM #table_B ; 
    

    查询时间

    MERGE #table_B AS target  
    USING ( SELECT col1, col2, colX FROM #table_A ) AS source (col1, col2, colX)  
    ON (target.colX = source.colX)  
    WHEN MATCHED THEN   
        UPDATE SET col1 = source.col1
            , col2 = source.col2 
    WHEN NOT MATCHED THEN  
        INSERT (col1, col2)  
        VALUES (source.col1, source.col2) 
    ;
    

    之后

    SELECT * FROM #table_A ;     
    SELECT * FROM #table_B ;
    

    认为您也可以使用MERGE 来更新#table_A 中的标志,但我不知道正确的语法。如果需要,您也可以在 MERGE 之后运行另一个 UPDATE

    MARK TABLE_A FLAG

    UPDATE #table_A
    SET flag = 1
    FROM #table_B
    WHERE #table_A.col1 = #table_B.col1
        AND #table_A.col2 = #table_B.col1
        AND #table_B.colX IS NOT NULL
    ;
    

    之后 选择 * 从 #table_A ;

    更多 MERGE 好东西: http://www.made2mentor.com/2012/07/got-the-urge-to-merge/

    【讨论】:

      【解决方案3】:

      如果您想提高性能,那么您需要查看基于 SET 的操作。 while 循环和游标基本上是一回事。

      更多详情请参考以下链接

      http://www.techrepublic.com/blog/the-enterprise-cloud/comparing-cursor-vs-while-loop-performance-in-sql-server-2008/
      

      【讨论】:

        猜你喜欢
        • 2014-06-02
        • 1970-01-01
        • 2011-03-22
        • 2011-10-16
        • 1970-01-01
        • 1970-01-01
        • 2012-09-21
        • 2011-04-21
        • 1970-01-01
        相关资源
        最近更新 更多