2010-02-23 58 views
0

這是一個存儲過程(至少我必須這樣假設),它構造一個Sql查詢爲一個String,然後用exec調用它。出於某種原因,自稱爲程序員的夥計,使用「〜」字符連接了一些值,並將其分割回應用程序層。這個SP打破時,一些複選框是「選擇」。問題是我怎樣才能調試這個噩夢。我發現當選中CheckBox時,它會在一些TypeCode的開頭添加一個不必要的「〜1」,並且它會中斷。如果沒有選擇,它按預期工作。 (順便說一句,我真的很想知道這種東西叫什麼樣的編碼實踐)。什麼是StoredProcedure

ALTER PROC [dbo].[BUTCEREP] @SirketKod varchar(10), @IlkTarih varchar(10), @SonTarih varchar(10), @Tip int, @Tur int, @MasrafMrk varchar(100), @DovizKod varchar(5), @MaliTKod varchar(10) 
    -- Tip 0-TarihAraligi; 1-2AylikButce; 2-YTDButce; 3-YTDCompPrev 
    -- Tur 0-Muhasebe 1-Gider 2-Butce 3-ButceMuhasebe 4-ButceGider 
    AS 
     declare 
     @SqlText nvarchar(4000), 
     @SqlBud varchar(4000), 
     @SqlMuh varchar(4000), 
     @SqlGid varchar(4000), 
     @xIlkT datetime, 
     @xSonT datetime, 
     @ThisMonth varchar(10), 
     @NextMonth varchar(10), 
     @ThisYear varchar(10), 
     @PrevYear varchar(10) 


     if (not @IlkTarih is null) set @xIlkT = CONVERT(datetime,@IlkTarih,103) 
     if (not @SonTarih is null) set @xSonT = CONVERT(datetime,@SonTarih,103) 
     set @DovizKod=IsNull(@DovizKod, '') 
     if @Tip=1 and MONTH(@xIlkT)=12 set @xIlkT = dateadd(month,-1,@xIlkT) 

     set @ThisMonth = CONVERT(varchar,MONTH(@xIlkT)) 
     set @NextMonth = CONVERT(varchar,MONTH(@xIlkT)+1) 
     set @ThisYear = CONVERT(varchar,YEAR(@xIlkT)) 
     set @PrevYear = CONVERT(varchar,YEAR(@xIlkT)-1) 

     set @SqlMuh='select X.MuhHesapKod,X.Tarih,SUM(CAST(X.Borc AS FLOAT)) Borc,'+ 
               'SUM(CAST(X.Alacak AS FLOAT)) Alacak' + 
        ' from (select CASE S.N WHEN 1 THEN LEFT(D.MuhHesapKod,3)' + 
             ' WHEN 2 THEN LEFT(D.MuhHesapKod,7)' + 
             ' ELSE D.MuhHesapKod END MuhHesapKod,' + 
           'D.Tarih,Borc,Alacak' + 
        ' from '[email protected]+'MUH_D D inner join '[email protected]+'MUH_H H on (H.SirketKod=D.SirketKod) and (H.KontrolNo=D.KontrolNo)'+ 
       ' CROSS JOIN dbo.SeriTable(3) S' + 
       ' where D.SirketKod=' + QuoteName(@SirketKod,'''') + 
        case when IsNull(@MasrafMrk,'')<>'' then ' and D.MasrafMrkKod in (select Kod from GetArray('+QuoteName(@MasrafMrk,'''')+'))' else '' end + 
        case @Tip 
        when 0 then ' and D.Tarih BETWEEN ' + IsNull(QuoteName(CONVERT(varchar,@xIlkT,103),''''),'D.Tarih') + ' and ' + IsNull(QuoteName(CONVERT(varchar,@xSonT,103),''''),'D.Tarih') 
        when 1 then ' and YEAR(D.Tarih)=' [email protected]+' and MONTH(D.Tarih) in ('[email protected]+','[email protected]+')' 
        when 2 then ' and YEAR(D.Tarih)=' [email protected]+' and MONTH(D.Tarih)<='[email protected] 
        when 3 then ' and (YEAR(D.Tarih)='[email protected]+' or (YEAR(D.Tarih)='[email protected]+' and MONTH(D.Tarih)<='[email protected]+'))' 
        end + 
        ' and IsNull(H.FisTip,'''')<>''KAPANIS'''+ 
          ') X' + 
       ' where X.MuhHesapKod in (select Kod from MALIT_M where SirketKod=' + QuoteName(@SirketKod,'''') + 
                    ' and MaliTKod=' + QuoteName(@MaliTKod,'''') + ')' + 
       ' group by X.MuhHesapKod,X.Tarih' 

     set @SqlMuh = ' select 1 Tip,CAST(4 AS char(1))+''~0~''+M.MuhHesapKod Kod,' + 
        case @Tip 
         when 0 then 'SUM((M.Borc-M.Alacak)) TopBak' 
         when 1 then 'SUM(CASE WHEN MONTH(M.Tarih)=' [email protected]+' THEN 1 ELSE 0 END*(M.Borc-M.Alacak)) A1Bak,' + 
            'SUM(CASE WHEN MONTH(M.Tarih)=' [email protected]+' THEN 1 ELSE 0 END*(M.Borc-M.Alacak)) A2Bak' 
         when 2 then 'SUM(CASE WHEN MONTH(M.Tarih)=' [email protected]+' THEN 1 ELSE 0 END*(M.Borc-M.Alacak)) A1Bak,' + 
            'SUM(CASE WHEN MONTH(M.Tarih)<='[email protected]+' THEN 1 ELSE 0 END*(M.Borc-M.Alacak)) A2Bak' 
         when 3 then 'SUM(CASE WHEN YEAR(M.Tarih)=' [email protected]+' AND MONTH(M.Tarih)=' [email protected]+' THEN 1 ELSE 0 END*(M.Borc-M.Alacak)) A1Bak,' + 
            'SUM(CASE WHEN YEAR(M.Tarih)=' [email protected]+' AND MONTH(M.Tarih)<='[email protected]+' THEN 1 ELSE 0 END*(M.Borc-M.Alacak)) A2Bak,' + 
            'SUM(CASE WHEN YEAR(M.Tarih)=' [email protected]+' THEN 1 ELSE 0 END*(M.Borc-M.Alacak)) A3Bak' 
        end + 
        ' from (' + @SqlMuh + ') M' + 
        ' where M.MuhHesapKod in (select Kod from MALIT_M where SirketKod=' + QuoteName(@SirketKod,'''') + 
                     ' and MaliTKod=' + QuoteName(@MaliTKod,'''') + ')'+ 
        ' group by M.MuhHesapKod' 

     set @SqlGid = ' select 1 Tip,CAST(2 AS char(1))+''~0~''+C.GiderKod Kod,' + 
        case @Tip 
         when 0 then 'SUM((2*C.IslemTuru-1)*'+CASE WHEN @DovizKod='' THEN '(TutarTL+GVergiTutar)' ELSE 'GEURO' END+') TopBak' 
         when 1 then 'SUM(CASE WHEN MONTH(C.Tarih)='[email protected]+' THEN 1 ELSE 0 END*(2*C.IslemTuru-1)*'+CASE WHEN @DovizKod='' THEN '(TutarTL+GVergiTutar)' ELSE 'GEURO' END+') A1Bak,' + 
            'SUM(CASE WHEN MONTH(C.Tarih)='[email protected]+' THEN 1 ELSE 0 END*(2*C.IslemTuru-1)*'+CASE WHEN @DovizKod='' THEN '(TutarTL+GVergiTutar)' ELSE 'GEURO' END+') A2Bak' 
         when 2 then 'SUM(CAST(CASE WHEN MONTH(C.Tarih)=' [email protected]+ ' THEN 1 ELSE 0 END*(2*C.IslemTuru-1)*'+CASE WHEN @DovizKod='' THEN '(TutarTL+GVergiTutar)' ELSE 'GEURO' END+' AS FLOAT)) A1Bak,' + 
            'SUM(CAST(CASE WHEN MONTH(C.Tarih)<='[email protected]+ ' THEN 1 ELSE 0 END*(2*C.IslemTuru-1)*'+CASE WHEN @DovizKod='' THEN '(TutarTL+GVergiTutar)' ELSE 'GEURO' END+' AS FLOAT)) A2Bak' 
         when 3 then 'SUM(CAST(CASE WHEN YEAR(C.Tarih)=' [email protected]+' AND MONTH(C.Tarih)=' [email protected]+ ' THEN 1 ELSE 0 END*(2*C.IslemTuru-1)*'+CASE WHEN @DovizKod='' THEN '(TutarTL+GVergiTutar)' ELSE 'GEURO' END+' AS FLOAT)) A1Bak,' + 
            'SUM(CAST(CASE WHEN YEAR(C.Tarih)=' [email protected]+' AND MONTH(C.Tarih)<='[email protected]+ ' THEN 1 ELSE 0 END*(2*C.IslemTuru-1)*'+CASE WHEN @DovizKod='' THEN '(TutarTL+GVergiTutar)' ELSE 'GEURO' END+' AS FLOAT)) A2Bak,' + 
            'SUM(CAST(CASE WHEN YEAR(C.Tarih)=' [email protected]+' THEN 1 ELSE 0 END*(2*C.IslemTuru-1)*'+CASE WHEN @DovizKod='' THEN '(TutarTL+GVergiTutar)' ELSE 'GEURO' END+' AS FLOAT)) A3Bak' 
        end + 
        ' from CHI_D C'+ 
        ' where C.GiderKod in (select Kod from MALIT_M where SirketKod=' + QuoteName(@SirketKod,'''') + 
                    ' and MaliTKod=' + QuoteName(@MaliTKod ,'''') + ')'+ 
        case when IsNull(@MasrafMrk,'')<>'' then ' and C.MasrafMrkKod in (select Kod from GetArray('+QuoteName(@MasrafMrk,'''')+'))' else '' end + 

        case @Tip 
         when 0 then ' and C.Tarih BETWEEN ' + IsNull(QuoteName(CONVERT(varchar,@xIlkT,103),''''),'C.Tarih') + ' and ' + IsNull(QuoteName(CONVERT(varchar,@xSonT,103),''''),'C.Tarih') + ')' 
         when 1 then ' and YEAR(C.Tarih)='[email protected]+' and MONTH(C.Tarih) in (' [email protected]+','[email protected]+')' 
         when 2 then ' and YEAR(C.Tarih)='[email protected]+' and MONTH(C.Tarih)<='[email protected] 
         when 3 then ' and (YEAR(C.Tarih)='[email protected]+' or (YEAR(C.Tarih)='[email protected]+' and MONTH(C.Tarih)<='[email protected]+'))' 
        end + 
        ' group by C.GiderKod' 

     set @SqlBud='select 0 Tip,CAST(D.IslemTipi AS char(1))+''~0~''+D.KalemKod Kod,' + 
        case @Tip 
        when 0 then 'sum((2*D.IslemTuru-1)*IsNull(D.Tutar,0)) TopBak' 
        when 1 then 'sum(CASE WHEN MONTH(D.BasTarih)='[email protected]+' THEN 1 ELSE 0 END*(2*D.IslemTuru-1)*IsNull(D.Tutar,0)) A1Bak,' + 
           'sum(CASE WHEN MONTH(D.BasTarih)='[email protected]+' THEN 1 ELSE 0 END*(2*D.IslemTuru-1)*IsNull(D.Tutar,0)) A2Bak' 
        when 2 then 'sum(CASE WHEN MONTH(D.BasTarih)='[email protected]+' THEN 1 ELSE 0 END*(2*D.IslemTuru-1)*IsNull(D.Tutar,0)) A1Bak,' + 
           'sum((2*D.IslemTuru-1)*IsNull(D.Tutar,0)) A2Bak' 
        when 3 then 'sum(CASE WHEN MONTH(D.BasTarih)=' [email protected]+' THEN 1 ELSE 0 END*(2*D.IslemTuru-1)*IsNull(D.Tutar,0)) A1Bak,' + 
           'sum(CASE WHEN MONTH(D.BasTarih)<='[email protected]+' THEN 1 ELSE 0 END*(2*D.IslemTuru-1)*IsNull(D.Tutar,0)) A2Bak,' + 
           'sum((2*D.IslemTuru-1)*IsNull(D.Tutar,0)) A3Bak' 
        end + 
        ' from dbo.GetButceList('+ QuoteName(@SirketKod,'''') +','+ IsNull(QuoteName(@MasrafMrk,''''),'null')+','+QuoteName(@DovizKod,'''')+',0) D' + 
        ' where D.KalemKod in (select Kod from MALIT_M where SirketKod=' + QuoteName(@SirketKod,'''') + 
                   ' and MaliTKod=' + QuoteName(@MaliTKod,'''') + ')'+ 
        case @Tip 
        when 0 then ' and D.BasTarih>=' + IsNull(QuoteName(CONVERT(varchar,@xIlkT,103),''''),'D.BasTarih') + ' and D.BitTarih<=' + IsNull(QuoteName(CONVERT(varchar,@xSonT,103),''''),'D.BitTarih') 
        when 1 then ' and YEAR(D.BasTarih)='[email protected]+' and MONTH(D.BasTarih) in (' [email protected]+','[email protected]+')' 
        when 2 then ' and YEAR(D.BasTarih)='[email protected]+' and MONTH(D.BasTarih)<='[email protected] 
        when 3 then ' and YEAR(D.BasTarih)='[email protected] 
        end + 
        ' group by D.KalemKod,D.IslemTipi' 

    -- Tur 0-Muhasebe 1-Gider 2-Butce 3-ButceMuhasebe 4-ButceGider 
     set @SqlText = case @Tur 
         when 0 then @SqlMuh 
         when 1 then @SqlGid 
         when 2 then @SqlBud 
         when 3 then @SqlBud + ' union all ' + @SqlMuh 
         when 4 then @SqlBud + ' union all ' + @SqlGid 
        end 

     if @Tip in (1,2) 
     set @SqlText='select Kod,' + 
          'SUM(CASE Tip WHEN 0 THEN IsNull(A1Bak,0) ELSE 0 END) A10Bak,' + --budget first 
          'SUM(CASE Tip WHEN 0 THEN IsNull(A2Bak,0) ELSE 0 END) A20Bak,' + --budget second 
          'SUM(CASE Tip WHEN 1 THEN IsNull(A1Bak,0) ELSE 0 END) A11Bak,' + --actual first 
          'SUM(CASE Tip WHEN 1 THEN IsNull(A2Bak,0) ELSE 0 END) A21Bak ' + --actual second 
         'from (' + @SqlText + ') X' + 
         ' group by Kod' 
     else if @Tip = 3 
     set @SqlText='select Kod,' + 
          'SUM(CASE Tip WHEN 1 THEN IsNull(A3Bak,0) ELSE 0 END) A00Bak,' + --actual prev 
          'SUM(CASE Tip WHEN 0 THEN IsNull(A1Bak,0) ELSE 0 END) A10Bak,' + --budget first 
          'SUM(CASE Tip WHEN 0 THEN IsNull(A2Bak,0) ELSE 0 END) A20Bak,' + --budget second 
          'SUM(CASE Tip WHEN 1 THEN IsNull(A1Bak,0) ELSE 0 END) A11Bak,' + --actual first 
          'SUM(CASE Tip WHEN 1 THEN IsNull(A2Bak,0) ELSE 0 END) A21Bak,' + --actual second 
          'SUM(CASE Tip WHEN 0 THEN IsNull(A3Bak,0) ELSE 0 END) A01Bak ' + --budget yearly 
         'from (' + @SqlText + ') X' + 
         ' group by Kod' 

     PRINT @SqlText 
     exec sp_executesql @SqlText 
+2

「問題是我該如何調試這個噩夢。」 - 像其他人一樣會這樣做。逐行瀏覽代碼,找出它的作用,用不同的參數對其進行測試,嘗試推斷業務規則並編寫錯誤修復程序或更換代碼(如果你敢的話)。 – Tomalak 2010-02-23 13:40:23

+0

如果問題是如何調試這個噩夢,爲什麼標題是「什麼是StoredProcedure」? – Ricket 2010-02-23 13:58:22

+0

只是意味着它很大... – AIC 2010-02-23 14:08:23

回答

2

你應該嘗試改寫這個使用CLR存儲過程

1

重寫將是最好的解決方案。但是,要嘗試調試它,請使用SQL Profiler(SQL Server附帶的SQL Server性能工具之一)將存儲過程跟蹤放到數據庫上,並捕獲執行此存儲過程的確切命令。這將允許您捕獲傳入的確切參數值,並允許您在SQL Management Studio窗口中反覆運行它。

然後,您可以修改存儲過程以在整個存儲過程的各個點上打印出希望檢查的各種值,以確定在任何給定點發生了什麼。

或者,您可以使用visual studio啓用SQL調試並實際執行存儲過程。從應用

INSERT INTO YourLog (TextValue) VALUES ('EXEC BUTCEREP @SirketKod='''+COALESCE(@SirketKod,'NULL')+''', @IlkTarih='''+COALESCE(@IlkTarih,'NULL')+''', ...) 

2)運行該程序數次捕捉:

+0

Visual Studio SQL調試適用於SQL Server 2008及更高版本。 – 2010-02-23 14:23:25

+0

我認爲這是SQL 2005及更高版本? – NYSystemsAnalyst 2010-02-23 15:02:34

0

1)在程序的頂部添加INSERT語句的輸入參數登錄到一臺,喜歡的東西輸入參數,包括幾個良好的運行以及知道的問題。

3)在代碼中添加許多PRINT語句。即使是長期的任務分解成更小的,但多任務(其中不同部分連接在一起時,「+」),並把它們之間的打印:

... 
PRINT @SqlMuh 
... 
PRINT @SqlMuh 
... 
PRINT @SqlGid 
... 

4)採取「EXEC ...」從字符串記錄並運行SSMS中的命令,查看打印輸出和代碼並確定發生了什麼。

+0

非常有趣的分析技術。謝謝。 – 2010-02-23 14:04:54

0

既然你問你怎麼可能調試此:

變化從今年年初:

ALTER PROC [dbo].[BUTCEREP] @SirketKod varchar(10), @IlkTarih varchar(10), @SonTarih varchar(10), @Tip int, @Tur int, @MasrafMrk varchar(100), @DovizKod varchar(5), @MaliTKod varchar(10) 
    -- Tip 0-TarihAraligi; 1-2AylikButce; 2-YTDButce; 3-YTDCompPrev 
    -- Tur 0-Muhasebe 1-Gider 2-Butce 3-ButceMuhasebe 4-ButceGider 
    AS 
     declare 
     @SqlText nvarchar(4000), 
     @SqlBud varchar(4000), 
     @SqlMuh varchar(4000), 
     @SqlGid varchar(4000), 
     @xIlkT datetime, 
     @xSonT datetime, 
     @ThisMonth varchar(10), 
     @NextMonth varchar(10), 
     @ThisYear varchar(10), 
     @PrevYear varchar(10) 

進入這個:

declare @SqlText as nvarchar(4000) 
    declare @SqlBud as varchar(4000) 
    declare @SqlMuh as varchar(4000) 
    declare @SqlGid as varchar(4000) 
    declare @xIlkT as datetime 
    declare @xSonT as datetime 
    declare @ThisMonth as varchar(10) 
    declare @NextMonth as varchar(10) 
    declare @ThisYear as varchar(10) 
    declare @PrevYear as varchar(10) 

    set @ThisYear = 'your test value' 
    set @NextMonth = 'your test value' 
    set @ThisMonth = 'your test value' 
    set @SqlText = 'your test value' 
    set @SqlBud = 'your test value' 
    set @SqlMuh = 'your test value' 
    set @SqlGid = 'your test value' 
    set @xIlkT = 'your test value' 
    set @xSonT = 'your test value' 
    set @PrevYear = 'your test value' 

和調試隨意。在以下部分之間追加選擇語句:

select @SqlMuh 

瞭解它們在特定位置的值。

一旦您對所做的更改感到滿意,請返回並更改SP。這將減少每次你想檢查某些東西時改變執行的重複任務。

0

去年我有一個這樣的項目,我發現最好的做法是創建一個具有標識字段和varchar字段的表,並在執行EXEC之前將@SqlText變量寫入它。通過這種方式,當您測試並查看結果時,您可以獲取已執行的最新SQL。

長期來說,我同意這裏的大多數人應該重新寫這篇文章(雖然這可能不是一個好的短期解決方案,除非這是唯一的SP)。

+0

一切都是這樣的..加上deplhi代碼(我不是delphi程序員);) – AIC 2010-02-23 14:35:05

0

這是動態SQL,您真的需要查看前面所述的配置文件,但使用底部的PRINT命令將顯示實際發送的內容,以便您可以進行調試。如果您不是SQL程序員,您將不會通過查看此代碼來進行調試。您需要將其打印出來,然後將打印的SQL複製到新窗口並調試該代碼。

要清楚我說的是第二次來的過程
PRINT @SqlText

最後一行這裏的另一個祕訣是良好的,在這一點上,你只需給它不同的值(我想從應用層或使用提到的聲明語句)並查找所有情況。當調試業務邏輯以將不同參數的流程圖或圖表作爲可視化助手時,我發現它很有幫助。通過註釋加入連線來理解關鍵關係。我想說最難的部分將是所有的日期轉換 - 還有很多重複的代碼應該放在函數中以提高可讀性。

有了分隔符('〜'),它很可能用於稍後解析數據,所以我也可以查看應用程序的其他層,它可能是錯誤甚至不存在,但是在在加載時在頁面級別進行更改。

在您的工作中,請務必對其進行評論,以便在您之後來的人不必從頭開始!