如何让这个SQL脚本运行得更快?

时间:2011-03-04 05:42:53

标签: sql sql-server performance tsql

我编写了脚本来对表中的值进行一些修复。但它需要永远完成..实际上从来没有看到它完成..只是挂在那里..任何点如何优化它将不胜感激。

有两个表:FundCorrespondencePreference,可以在记录中检查一些IDContacts列。如果选中它们,则ContentManagementRights表中应存在相应的记录(除了某些字段外几乎相同的字段)。

我们的想法是通过ContentManagemtnRights并找到所有独特的记录组合 4列,选择一些列值并从FundCorrespondencePreference table收集所有用户,然后检查该用户是否已选中该用户, 返回ContentManagementRights表并检查是否存在此类记录,如果不存在,则在列中插入具有相应值的记录。

希望我或多或少地连贯地解释它。无论如何,感谢您的时间和建议。这是剧本:

--the script will check if any of the contacts for a partner in FundCorrespondencePreferences are missing in ContentManagementRight table
-- some of the contacts in FundCorrespondencePreference just not appear in ContentManagementRight as checked

    declare @IDFundInfo char(30)
    declare @IDCompany char(30)
    declare @IDFundTransactionParameter char(30)
    declare @IDContentManagement char(30)
    declare @IDUserInfo char(30)
    declare @ID char(30)

    declare @curContentManagementRights cursor
    set @curContentManagementRights = cursor fast_forward for
    --first select distinct records from ContentManagementRights for IDFundInfo, IDCompany,IDFundTransactionParameter and IDContentManagement where
    --bFundLevelAccess == 0
    SELECT distinct
       ContentManagementRights.IDFundInfo, 
       ContentManagementRights.IDCompany, 
       ContentManagementRights.IDFundTransactionParameter, 
       ContentManagementRights.IDContentManagement
    FROM ContentManagementRights 
    WHERE     
       (ContentManagementRights.bFundLevelAccess = 0)
    ORDER BY 
       idfundinfo, idcompany,idfundtransactionparameter, idcontentmanagement

    open @curContentManagementRights;
    fetch from @curContentManagementRights into @IDFundInfo, @IDCompany,@IDFundTransactionParameter,@IDContentManagement

    WHKLE @@fetch_status = 0
    BEGIN
        --get all IDContactInfo for the chosen fund, partnerid,fundtranactionparameterid from fundcorrespondencepreference table + make sure that at least one correspTO parameter

       declare @curFundCorrespondencePreference cursor
       set @curFundCorrespondencePreference = cursor fast_forward for 
         SELECT     
             UserInfo.IDUserInfo
         FROM         
             FundCorrespondencePreference 
         INNER JOIN
             FundTransactionParameter ON FundCorrespondencePreference.IDFundTransactionParameter = FundTransactionParameter.IDFundTransactionParameter 
         INNER JOIN
             ContactInfo ON FundCorrespondencePreference.IDContactInfo = ContactInfo.IDContactInfo 
         INNER JOIN
             UserInfo ON ContactInfo.IDContactInfo = UserInfo.IDContactInfo 
         INNER JOIN
             UserGroupInfo ON UserInfo.IDUserInfo = UserGroupInfo.IDUserInfo 
         INNER JOIN
             GroupInfo ON UserGroupInfo.IDGroupInfo = GroupInfo.IDGroupInfo
         WHERE     
            (FundTransactionParameter.IDFundInfo = @IDFundInfo) 
            AND (FundCorrespondencePreference.IDCompany = @IDCompany) 
            AND (FundCorrespondencePreference.IDFundTransactionParameter = @IDFundTransactionParameter) 
            AND (FundCorrespondencePreference.bEmail = 1) 
            AND (GroupInfo.sName = N'Xtranet Partner Group') 
            OR (FundCorrespondencePreference.bFax = 1) 
            OR (FundCorrespondencePreference.bLetterTo = 1) 
            OR (FundCorrespondencePreference.bLetterCc = 1) 
            OR (FundCorrespondencePreference.bEmailCc = 1) 
            OR (FundCorrespondencePreference.bFaxCc = 1)

          --go through all the contacts chosen from FundCorrespondencePreference table and 
          --if not present in ContentManagementRight table, insert into the table record with previously selected parameters
          open @curFundCorrespondencePreference;
          fetch from @curFundCorrespondencePreference into @IDUserInfo

          WHILE @@fetch_status = 0
          BEGIN
            if 
               (Select Count(IDContentManagementRights) 
                from ContentManagementRights 
                where 
                   IDContentManagement = @IDContentManagement 
                   and IDFundInfo = @IDFundInfo 
                   and IDCompany = @IDCompany 
                   and IDUserInfo = @IDUserInfo) = 0
             begin
            --insert a new record in ContentManagementRights if there is none for chosen parameters
            Exec GetNextID 'ContentManagementRights', @ID output
            INSERT INTO ContentManagementRights (IDContentManagementRights,IDContentManagement,IDFundInfo,IDCompany,sCreatedBy,dtCreatedDate,sUpdatedBy,dtUpdatedDate,IDUserInfo,IDFundTransactionParameter,bFundLevelAccess)
            VALUES (@ID,@IDContentManagement,@IDFundInfo,@IDCompany,'admin',GETDATE(),'admin',GETDATE(),@IDUserInfo,@IDFundTransactionParameter,0)          
              end
         end
        close @curFundCorrespondencePreference;
        deallocate @curFundCorrespondencePreference;
    --      
        end

    close @curContentManagementRights;
    deallocate @curContentManagementRights;

2 个答案:

答案 0 :(得分:1)

我不认为很多人会读那么长的查询。逻辑是多余的。

例如if(select count(something)= 0)你可以用having子句替换并消除嵌套游标的额外使用。

以下代码仅供参考。在代码中有条款之前我没有把'group by'放进去。希望它有所帮助。

我的提示是,SQL是数据操作语言。不像OOP编程那样单个对象。我说这是因为你尝试使用游标来处理每一行,这是OOP编程风格,例如。 for循环在每一行中都有效。 但是sql打算一次在多行上工作。尝试使用聚合,而不是

的情况
   declare @IDFundInfo char(30)
    declare @IDCompany char(30)
    declare @IDFundTransactionParameter char(30)
    declare @IDContentManagement char(30)
    declare @IDUserInfo char(30)
    declare @ID char(30)

    declare @curContentManagementRights cursor
    set @curContentManagementRights = cursor fast_forward for
    --first select distinct records from ContentManagementRights for IDFundInfo, IDCompany,IDFundTransactionParameter and IDContentManagement where
    --bFundLevelAccess == 0
    SELECT distinct
       ContentManagementRights.IDFundInfo, 
       ContentManagementRights.IDCompany, 
       ContentManagementRights.IDFundTransactionParameter, 
       ContentManagementRights.IDContentManagement
    FROM ContentManagementRights 
    WHERE     
       (ContentManagementRights.bFundLevelAccess = 0)
    ORDER BY 
       idfundinfo, idcompany,idfundtransactionparameter, idcontentmanagement

    open @curContentManagementRights;
    fetch from @curContentManagementRights into @IDFundInfo, @IDCompany,@IDFundTransactionParameter,@IDContentManagement

    WHKLE @@fetch_status = 0
    BEGIN
        --get all IDContactInfo for the chosen fund, partnerid,fundtranactionparameterid from fundcorrespondencepreference table + make sure that at least one correspTO parameter

     INSERT INTO ContentManagementRights (IDContentManagementRights,IDContentManagement,IDFundInfo,IDCompany,sCreatedBy,dtCreatedDate,sUpdatedBy,dtUpdatedDate,IDUserInfo,IDFundTransactionParameter,bFundLevelAccess)
         SELECT     
             @ID,@IDContentManagement,@IDFundInfo,@IDCompany,'admin',GETDATE(),'admin',GETDATE(),UserInfo.IDUserInfo,@IDFundTransactionParameter,0
         FROM         
             FundCorrespondencePreference 
         INNER JOIN
             FundTransactionParameter ON FundCorrespondencePreference.IDFundTransactionParameter = FundTransactionParameter.IDFundTransactionParameter 
         INNER JOIN
             ContactInfo ON FundCorrespondencePreference.IDContactInfo = ContactInfo.IDContactInfo 
         INNER JOIN
             UserInfo ON ContactInfo.IDContactInfo = UserInfo.IDContactInfo 
         INNER JOIN
             UserGroupInfo ON UserInfo.IDUserInfo = UserGroupInfo.IDUserInfo 
         INNER JOIN
             GroupInfo ON UserGroupInfo.IDGroupInfo = GroupInfo.IDGroupInfo
         WHERE     
            (FundTransactionParameter.IDFundInfo = @IDFundInfo) 
            AND (FundCorrespondencePreference.IDCompany = @IDCompany) 
            AND (FundCorrespondencePreference.IDFundTransactionParameter = @IDFundTransactionParameter) 
            AND (FundCorrespondencePreference.bEmail = 1) 
            AND (GroupInfo.sName = N'Xtranet Partner Group') 
            OR (FundCorrespondencePreference.bFax = 1) 
            OR (FundCorrespondencePreference.bLetterTo = 1) 
            OR (FundCorrespondencePreference.bLetterCc = 1) 
            OR (FundCorrespondencePreference.bEmailCc = 1) 
            OR (FundCorrespondencePreference.bFaxCc = 1)

    having count(IDContentManagementRights) = 0

        end

    close @curContentManagementRights;
    deallocate @curContentManagementRights;

答案 1 :(得分:1)

先生或女士,你做得很好,拒绝等到剧本完成工作。这里有两个游标,没有一个滚动到第一行之外。该剧本确实需要永远完成。 (好吧,只要系统可以保持工作,无论如何。)

你真的需要在每个循环中(通常在循环的end之前)放入它们的关联fetch from...指令,与每个循环之前的指令相同。