2016-05-26 13 views
0

私は、SQL Server 2012年のテーブルの上に次のトリガーがあります。私は、テーブル内の他の列への更新後のテーブルで実行中の合計を計算するためにトリガーを取得していますトリガーロック表計算、積算合計

CREATE TRIGGER [dbo].[UpdateTotals] 
    ON [dbo].[DEC10assessmentData] 
    AFTER UPDATE 
AS 
BEGIN 
    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    SET NOCOUNT ON; 

    --update list pract test 1 total 
    if update (list_practTest1_s1) or update (list_practTest1_s2) 
    begin 
     update DEC10assessmentData 
     set list_practTest1_total = CAST(list_practTest1_s1 AS decimal(3 , 1)) + CAST(list_practTest1_s2 AS decimal(3 , 1)) 
     where 
      TRY_CONVERT(decimal(3 , 1) , dbo.DEC10assessmentData.list_practTest1_s1) IS NOT NULL 
      and TRY_CONVERT(decimal(3 , 1) , dbo.DEC10assessmentData.list_practTest1_s2) IS NOT NULL 
     update DEC10assessmentData 
     set list_practTest1_total = NULL 
     where 
      TRY_CONVERT(decimal(3 , 1) , dbo.DEC10assessmentData.list_practTest1_s1) IS NULL 
      or TRY_CONVERT(decimal(3 , 1) , dbo.DEC10assessmentData.list_practTest1_s2) IS NULL 
    end 

    --update list test 1 total 
    if UPDATE (list_test1_s1) or update (list_test1_s2) 
    begin 
     update DEC10assessmentData 
     set list_test1_total = CAST(list_test1_s1 AS decimal(3 , 1)) + CAST(list_test1_s2 AS decimal(3 , 1)) 
     where 
      TRY_CONVERT(decimal(3 , 1) , dbo.DEC10assessmentData.list_test1_s1) IS NOT NULL 
      and TRY_CONVERT(decimal(3 , 1) , dbo.DEC10assessmentData.list_test1_s2) IS NOT NULL 
     update DEC10assessmentData 
     set list_test1_total = NULL 
     where 
      TRY_CONVERT(decimal(3 , 1) , dbo.DEC10assessmentData.list_test1_s1) IS NULL 
      or TRY_CONVERT(decimal(3 , 1) , dbo.DEC10assessmentData.list_test1_s2) IS NULL 
    end 

    --update list pract test 2 total 
    if update (list_practTest2_s1) or update (list_practTest2_s2) 
    begin 
     update DEC10assessmentData 
     set list_practTest2_total = CAST(list_practTest2_s1 AS decimal(3 , 1)) + CAST(list_practTest2_s2 AS decimal(3 , 1)) 
     where 
      TRY_CONVERT(decimal(3 , 1) , dbo.DEC10assessmentData.list_practTest2_s1) IS NOT NULL 
      and TRY_CONVERT(decimal(3 , 1) , dbo.DEC10assessmentData.list_practTest2_s2) IS NOT NULL 
     update DEC10assessmentData 
     set list_practTest2_total = NULL 
     where 
      TRY_CONVERT(decimal(3 , 1) , dbo.DEC10assessmentData.list_practTest2_s1) IS NULL 
      or TRY_CONVERT(decimal(3 , 1) , dbo.DEC10assessmentData.list_practTest2_s2) IS NULL 
    end 

    --update list test 2 total 
    if UPDATE (list_test2_s1) or update (list_test2_s2) 
    begin 
     update DEC10assessmentData 
     set list_test2_total = CAST(list_test2_s1 AS decimal(3 , 1)) + CAST(list_test2_s2 AS decimal(3 , 1)) 
     where 
      TRY_CONVERT(decimal(3 , 1) , dbo.DEC10assessmentData.list_test2_s1) IS NOT NULL 
      and TRY_CONVERT(decimal(3 , 1) , dbo.DEC10assessmentData.list_test2_s2) IS NOT NULL 
     update DEC10assessmentData 
     set list_test2_total = NULL 
     where 
      TRY_CONVERT(decimal(3 , 1) , dbo.DEC10assessmentData.list_test2_s1) IS NULL 
      or TRY_CONVERT(decimal(3 , 1) , dbo.DEC10assessmentData.list_test2_s2) IS NULL 
    end 

    --update read total 
    update DEC10assessmentData 
    set read_total = ((read_test1_Scaled/100 * 8) + (read_test2_scaled/100 * 12))/20 * 100 
    where 
     read_test1_Scaled is not null and read_test2_scaled is not null 

    --update read total to null where scores don't exist 
    update DEC10assessmentData 
    set read_total = NULL 
    where 
     read_test1_Scaled is null or read_test2_scaled is null 

    --update write total 
    update DEC10assessmentData 
    set writ_total = (CAST(writ_literatureReview as decimal(3,1))/100 * 4 
         + CAST(writ_exposition as decimal(3,1))/100 * 8 
         + CAST(writ_groupReport as decimal(3,1))/100 * 8 
         + cast(writ_synthSummary as decimal(3,1))/100 * 8 
         + cast(writ_critEvaluation as decimal(3,1))/100 * 12)/40 * 100 
    where 
     TRY_CONVERT(decimal(3 , 1) , writ_literatureReview) is not null and 
     TRY_CONVERT(decimal(3 , 1) , writ_exposition) is not null and 
     TRY_CONVERT(decimal(3 , 1) , writ_groupReport) is not null and 
     TRY_CONVERT(decimal(3 , 1) , writ_synthSummary) is not null and 
     TRY_CONVERT(decimal(3 , 1) , writ_critEvaluation) is not null 

    --update write total where scores don't exist 
    update DEC10assessmentData 
    set writ_total = NULL 
    where 
     TRY_CONVERT(decimal(3 , 1) , writ_literatureReview) is null or 
     TRY_CONVERT(decimal(3 , 1) , writ_exposition) is null or 
     TRY_CONVERT(decimal(3 , 1) , writ_groupReport) is null or 
     TRY_CONVERT(decimal(3 , 1) , writ_synthSummary) is null or 
     TRY_CONVERT(decimal(3 , 1) , writ_critEvaluation) is null 

    --update list total 
    update DEC10assessmentData 
    set list_total = ((list_test1_scaled/100 * 8) + (list_test2_scaled/100 * 12))/20 * 100 
    where 
     list_test1_scaled is not null and list_test2_scaled is not null 

    --update list total to null where scores don't exist 
    update DEC10assessmentData 
    set list_total = NULL 
    where 
     list_test1_scaled is null or list_test2_scaled is null 

    --update speak total 
    update DEC10assessmentData 
    set speak_total = (cast(speak_groupPres as decimal(3,1))/100 * 4 
         + CAST(speak_indivPres as decimal(3,1))/100 * 8 
         + cast(speak_tutorialDiscus as decimal(3,1))/100 * 8)/20 * 100 
    where 
     TRY_CONVERT(decimal(3 , 1) , speak_groupPres) is not null and 
     TRY_CONVERT(decimal(3 , 1) , speak_indivPres) is not null and 
     TRY_CONVERT(decimal(3 , 1) , speak_tutorialDiscus) is not null 

    --update speak total where scores don't exist to null 
    update DEC10assessmentData 
    set speak_total = NULL 
    where 
     TRY_CONVERT(decimal(3 , 1) , speak_groupPres) is null or 
     TRY_CONVERT(decimal(3 , 1) , speak_indivPres) is null or 
     TRY_CONVERT(decimal(3 , 1) , speak_tutorialDiscus) is null 

    --update overall score 
    update DEC10assessmentData 
    set overall_total = (read_total + writ_total * 2 + list_total + speak_total)/5 

    --update rec/not rec's for skills and overall 
    update DEC10assessmentData 
    set read_rec = t.rec_read, writ_rec = t.rec_writ, list_rec = t.rec_list, speak_rec = t.rec_speak, overall_rec = t.rec_overall 
    from dbo.udf_getDEC10RecSkillAndOverall() as t inner join DEC10assessmentData 
    on t.studentID = DEC10assessmentData.studentID and t.assessmentLookup = DEC10assessmentData.assessmentLookup 

    --update rec/not rec's for final rec 
    update DEC10assessmentData 
    set final_rec = t.rec_final 
    from dbo.udf_getDEC10RecFinal() as t inner join DEC10assessmentData 
    on t.studentID = DEC10assessmentData.studentID and t.assessmentLookup = DEC10assessmentData.assessmentLookup 

END 

GO 

を。ご覧のとおり、残念ながらvarchar値のキャストはたくさんありますが、1つの問題、つまりロックを除いては機能します。

私は断続的にユーザーに更新を実行できないと訴えています。これは、トリガーがテーブルをロックしているためです。これを避ける方法はありますか?そして、これがどうなっているのかをどうやって確認するのですか?トリガーが更新する列は更新されません。

私はErland Sommarskogのbeta_lockinfoを使用してデッドロック2つの更新から次のような出力が得られます。

rsctype locktype lstatus ownertype waittime spid waittype 
KEY   U WAIT TRANSACTION  2.192  LCK_M_U 69 
DATABASE S grant STW      69 
KEY   X grant TRANSACTION    69 
OBJECT  IX grant TRANSACTION    69 
PAGE  IU grant TRANSACTION    69 
PAGE  IX grant TRANSACTION    69 
KEY   U WAIT TRANSACTION  2.188  LCK_M_U 89 
DATABASE S grant STW      89 
KEY   X grant TRANSACTION    89 
OBJECT  IX grant TRANSACTION    89 
PAGE  IU grant TRANSACTION    89 
PAGE  IX grant TRANSACTION    89 

答えて

1

最初のアドバイスは、おそらく使用のトリガを行うと、他のいくつかの層にビジネスロジックを移動しないようにする必要があります。

あなたの更新がテーブル全体に影響を与え、それはおそらく、テーブルロックを生成します。

update DEC10assessmentData 
set overall_total = (read_total + writ_total * 2 + list_total + speak_total)/5 
etc 

なぜ変更されたもの以外の行を更新しますか? How to work only on the updated row

計算には、use calculated columns instead

あなたは本当にすべての変換を行う必要がありますか?代わりにテーブル定義でデータ型を修正できませんか?

しかし、これが本当にトリガーと関係していれば、テーブルをリファクタリングして同じテーブルに2つのデータを格納しないようにすることができます。こうすることで、ユーザーは自分のデータを更新でき、更新することができます。