使用SQL Server

时间:2016-03-24 10:29:50

标签: sql-server join sql-update cursor dynamicquery

请帮助我优化此代码,或者让我知道我是否可以更好地完成此操作。

请求:我正在更新Product表,其中包含产品信息。

  • 想法是通过join从其他表中获取一些列。 (curTaxonomy正在这样做。)
  • 然后将获取的记录更新为Product表。
  • 但在此之前,我需要检查我在product表中更新的列是否为NULL或具有不同的值(与来自连接的值不同)。
  • 如果这些条件匹配,则只更新列。

我正在使用游标来获取记录并创建动态更新查询,这将更新记录。

代码:

CREATE PROCEDURE [dbo].[UpdateProdCatalog]
AS
BEGIN

DECLARE @Tier_1_Tbl NVARCHAR(100) = NULL
DECLARE @Tier_2_Tbl NVARCHAR(100) = NULL    
DECLARE @Flag_Tbl NVARCHAR(100) = NULL

DECLARE @Tier_1 NVARCHAR(100) = NULL
DECLARE @Tier_2 NVARCHAR(100) = NULL
DECLARE @Flag NVARCHAR(100) = NULL  

DECLARE CurTaxonomy CURSOR FOR 
SELECT   CFR.T1, 
         CFR.T2, 
         CFR.Flag
FROM ProductCatalogue MPC
JOIN ControlFlow1 CF ON MPC.Product_Code = CF.Product_Code
JOIN ControlFlow2 CFR ON CF.MajorFamily = CFR.Product_Family
WHERE MPC.Manufacturer_Name = 'DELL';       

OPEN CurTaxonomy
IF @@CURSOR_ROWS > 0    
FETCH NEXT FROM CurTaxonomy INTO @Tier_1,@Tier_2,@Flag  
WHILE @@Fetch_status = 0        
    BEGIN           
    --print @Tier_1 + ' : '+ @Tier_2 + ' : '+ @Flag

        DECLARE CurProd CURSOR FOR 
        SELECT  MPC.Tier_1, 
                MPC.Tier_2, 
                MPC.Flag
        FROM ProductCatalogue MPC   
        WHERE MPC.Manufacturer_Name = 'DELL'

        OPEN CurProd
        IF @@CURSOR_ROWS > 0            
        FETCH NEXT FROM CurProd INTO @Tier_1_Tbl,@Tier_2_Tbl,@Flag_Tbl
        WHILE @@Fetch_status = 0        
            BEGIN                   
                --print @Tier_1_Tbl + ' : '+ @Tier_2_Tbl + ' : '+ @Flag_Tbl

                DECLARE @sqlCommand VARCHAR(8000)       
                DECLARE @Starter VARCHAR(100)

                --Generating dynamic update Query
                SET @Starter = 'SET '                   
                SET @sqlCommand = 'UPDATE ProductCatalogue '                
                BEGIN               
                    IF ( @Tier_1 IS NOT NULL) AND (@Tier_1_Tbl IS NULL or @Tier_1_Tbl <> @Tier_1) 
                        BEGIN   SET @sqlCommand = @sqlCommand + @Starter + 'Tier_1 = ''' + @Tier_1 + ''''  SET @Starter = ', ' END
                    IF ( @Tier_2 IS NOT NULL)  AND (@Tier_2_Tbl IS NULL or @Tier_2_Tbl <> @Tier_2) 
                        BEGIN   SET @sqlCommand = @sqlCommand + @Starter + 'Tier_2 = ''' + @Tier_2 + ''''  SET @Starter = ', ' END
                    IF ( @Flag IS NOT NULL) AND (@Flag_Tbl IS NULL or @Flag_Tbl <> @Flag) 
                        BEGIN   SET @sqlCommand = @sqlCommand + @Starter + 'Flag = ''' + @Flag + ''''  SET @Starter = ', ' END  
                END             

                IF (@Starter = ', ')
                BEGIN           
                    SET @sqlCommand = @sqlCommand + @Starter + ' Last_Modify_Date = ''' + CONVERT(VARCHAR(22),SYSDATETIME(),121) + '''' 
                    SET @sqlCommand = @sqlCommand + ' FROM ProductCatalogue MPC 
                        JOIN ControlFlow1 CF ON MPC.Product_Code = CF.Product_Code
                        JOIN ControlFlow2 CFR ON CF.MajorFamily = CFR.Product_Family 
                        WHERE MPC.Manufacturer_Name = ''' + 'DELL' + ''''               

                    EXEC (@sqlCommand)
                END     

            FETCH NEXT FROM CurProd INTO @Tier_1_Tbl,@Tier_2_Tbl,@Flag_Tbl
        END
        CLOSE CurProd
        DEALLOCATE CurProd  

    FETCH NEXT FROM CurTaxonomy INTO @Tier_1,@Tier_2,@Flag
END
CLOSE CurTaxonomy
DEALLOCATE CurTaxonomy  
END

我担心的是,这两个游标会运行一些 n x m 次,并且它也会为所有记录更新相同的值。我甚至试过这个工作正常。

update ProductCatalogue  
set Tier_1 = CFR.T1, 
    Tier_2 = CFR.T2, 
    Flag=CFR.Flag, 
    Last_Modify_Date = SYSDATETIME()
from ProductCatalogue MPC
join ControlFlow1 CF on MPC.Product_Code = CF.Product_Code
join ControlFlow2 CFR on CF.MajorFamily = CFR.Product_Family;

但我还需要检查product表中的现有记录并满足上述要求。如果有更好的方法可以做同样的事情,我将非常感激。

1 个答案:

答案 0 :(得分:0)

到目前为止,我已经提出了这个解决方案....但是光标执行仍会循环 N x M 次。

代码:

    CREATE PROCEDURE [dbo].[UpdateProdCatalog]
AS
BEGIN

    DECLARE @Product_Code_Tbl NVARCHAR(100) = NULL
    DECLARE @Tier_1_Tbl NVARCHAR(100) = NULL
    DECLARE @Tier_2_Tbl NVARCHAR(100) = NULL    
    DECLARE @Flag_Tbl NVARCHAR(100) = NULL  

    DECLARE @Product_Code NVARCHAR(100) = NULL
    DECLARE @Tier_1 NVARCHAR(100) = NULL
    DECLARE @Tier_2 NVARCHAR(100) = NULL
    DECLARE @Flag NVARCHAR(100) = NULL          

    DECLARE CurTaxonomy CURSOR FOR 
    SELECT   MPC.Product_Code,
             CFR.T1, 
             CFR.T2, 
             CFR.Flag
    FROM ProductCatalogue MPC
    JOIN ControlFlow1 CF ON MPC.Product_Code = CF.Product_Code
    JOIN ControlFlow2 CFR ON CF.MajorFamily = CFR.Product_Family
    WHERE MPC.Manufacturer_Name = 'DELL';       

    OPEN CurTaxonomy
    IF @@CURSOR_ROWS > 0    
    FETCH NEXT FROM CurTaxonomy INTO @Product_Code, @Tier_1,@Tier_2,@Flag   
    WHILE @@Fetch_status = 0        
        BEGIN                   
            DECLARE CurProd CURSOR FOR 
            SELECT  MPC.Product_Code,
                    MPC.Tier_1, 
                    MPC.Tier_2, 
                    MPC.Flag
                FROM ProductCatalogue MPC
                JOIN ControlFlow1 CF ON MPC.Product_Code = CF.Product_Code  
                JOIN ControlFlow2 CFR ON CF.MajorFamily = CFR.Product_Family
                WHERE MPC.Manufacturer_Name = 'DELL'

            OPEN CurProd
            IF @@CURSOR_ROWS > 0            
            FETCH NEXT FROM CurProd INTO @Product_Code_Tbl,@Tier_1_Tbl,@Tier_2_Tbl,@Flag_Tbl
            WHILE @@Fetch_status = 0        
                BEGIN               
                    DECLARE @sqlCommand VARCHAR(8000)       
                    DECLARE @Starter VARCHAR(100)

                    SET @Starter = 'SET '
                    SET @sqlCommand = 'UPDATE ProductCatalogue '

                    if (@Product_Code IS NOT NULL) AND (@Product_Code_Tbl = @Product_Code)
                    BEGIN           

                        IF ( @Tier_1 IS NOT NULL) AND (@Tier_1_Tbl IS NULL or @Tier_1_Tbl <> @Tier_1) 
                            BEGIN   SET @sqlCommand = @sqlCommand + @Starter + 'Tier_1 = ''' + @Tier_1 + ''''  SET @Starter = ', ' END
                        IF ( @Tier_2 IS NOT NULL) AND (@Tier_2_Tbl IS NULL or @Tier_2_Tbl <> @Tier_2) 
                            BEGIN   SET @sqlCommand = @sqlCommand + @Starter + 'Tier_2 = ''' + @Tier_2 + ''''  SET @Starter = ', ' END
                        IF ( @Flag IS NOT NULL) AND (@Flag_Tbl IS NULL or @Flag_Tbl <> @Flag) 
                            BEGIN   SET @sqlCommand = @sqlCommand + @Starter + 'Flag = ''' + @Flag + ''''  SET @Starter = ', ' END  
                    END                 

                    IF (@Starter = ', ')
                    BEGIN           
                        SET @sqlCommand = @sqlCommand + @Starter + ' Last_Modify_Date = ''' + CONVERT(VARCHAR(22),SYSDATETIME(),121) + '''' 
                        SET @sqlCommand = @sqlCommand +  ' WHERE Product_Code = ''' + @Product_Code + ''' and Manufacturer_Name = ''' + 'DELL' + ''''                   
                        EXEC (@sqlCommand)
                    END     

                FETCH NEXT FROM CurProd INTO @Product_Code_Tbl,@Tier_1_Tbl,@Tier_2_Tbl,@Flag_Tbl
            END
            CLOSE CurProd
            DEALLOCATE CurProd  

        FETCH NEXT FROM CurTaxonomy INTO @Product_Code, @Tier_1,@Tier_2,@Flag   
    END
    CLOSE CurTaxonomy
    DEALLOCATE CurTaxonomy  
END
GO