2013-02-28 57 views
0

我正在寫一個網站上使用的查詢。當需要查詢時,它直接被解析到服務器,結果全部由查詢控制。該網站只是返回表格。我在網站上做的是客戶端可以選擇的複選框,並將這些複選框解析爲查詢@var = 1@var = 0。正因爲如此,現在我有這個代碼來檢查和添加或不取決於它是否被檢查。我的問題是,有沒有更好的辦法去這比使用IF聲明是這樣,因爲我有代碼的幾個部分,其中包括這樣的:比使用IF更適合這種情況嗎?

SET @sql = 'select distinct ' 
If @mgchk = 1 
    SET @sql = @sql + 'p.MainGroup' 
If @sgchk = 1 and @sql = 'select distinct ' 
    SET @sql = @sql + 'p.SubGroup' 
If @sgchk = 1 and @sql not like '%SubGroup' 
    SET @sql = @sql + ',p.SubGroup' 
If @ssgchk = 1 and @sql = 'select distinct ' 
    SET @sql = @sql + 'p.SubSubGroup' 
If @ssgchk = 1 and @sql not like '%SubSubGroup' 
    SET @sql = @sql + ',p.SubSubGroup' 
If @Seasonchk = 1 and @sql = 'select distinct ' 
    SET @sql = @sql + 'p.Season' 
If @Seasonchk = 1 and @sql not like '%Season' 
    SET @sql = @sql + ',p.Season' 
If @vendorchk = 1 and @sql = 'select distinct ' 
    SET @sql = @sql + 'p.VendorID' 
If @vendorchk = 1 and @sql not like '%VendorID' 
    SET @sql = @sql + ',p.VendorID' 

SET @sql = 
    @sql + 
    ' into 
     ##aa 
    from 
     RPProducts p, 
     RPIv i, 
     RPTrsd d, 
     RPTrs s 
    WHERE 
    s.StoreID = d.StoreID and 
     s.ReceiptNO = d.ReceiptNO and 
     i.UPC = d.UPC and 
     i.StoreID = d.StoreID and 
     i.IVProduct = p.Productid and 
     s.TRSdate >= '''+ convert(varchar(10), @trsfrom, 101) +''' and 
     s.TRSdate <= '''+ convert(varchar(10), @trsto, 101) +'''' 
execute sp_executesql @sql 

@mgchk/@sgchk/@ssgchk/@seasonchk/@vendorchk是複選框變量

要回答@Aaron,

全局臨時因爲動態查詢。整個查詢得到處理並在數據被拖動時立即丟棄。沒有衝突會發生在那裏。

我的日期變量是datetime,它在動態SQL中給我一個錯誤。

是的,回想一下同樣的事情來檢查,這是整個問題的原因,如果有更好的使用比IF檢查。

,我發現使用別名連接更容易...

+1

哦哇,這麼多東西在這裏挑選...全球##臨時表,爲什麼?日期爲區域字符串,爲什麼?爲什麼要檢查你添加的列是否是第一個?舊式連接,爲什麼? – 2013-02-28 15:28:47

+0

@AaronBertrand - 更新後的答案 – JohnZ 2013-02-28 15:39:09

+0

你有沒有試過讓兩個用戶同時運行這個存儲過程?關於你稱之爲「別名連接」的內容 - [請閱讀本文全文,包括評論](http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/08/bad-habits-to-kick-using -old的風格,joins.aspx)。 – 2013-02-28 15:40:39

回答

4
-- rather than convert to a dangerously formatted string, 
-- here is a much better way to strip time from a datetime 
-- (if you need to!) 

SET @trsfrom = DATEADD(DAY, DATEDIFF(DAY, 0, @trsfrom), 0); 
SET @trsto = DATEADD(DAY, DATEDIFF(DAY, 0, @trsto), 0); 

DECLARE @sql NVARCHAR(MAX) = N'SELECT DISTINCT '; 

-- here's an easier way to strip the first comma: 

SET @sql += SUBSTRING(
    CASE WHEN @mgchk  = 1 THEN ',p.MainGroup' ELSE '' END 
    + CASE WHEN @sgchk  = 1 THEN ',p.SubGroup' ELSE '' END 
    + CASE WHEN @ssgchk = 1 THEN ',p.SubSubGroup' ELSE '' END 
    + CASE WHEN @Seasonchk = 1 THEN ',p.Season'  ELSE '' END 
    + CASE WHEN @vendorchk = 1 THEN ',p.VendorID' ELSE '' END, 2, 2000); 

SET @sql += ' INTO ##aa 
    FROM 
     dbo.RPProducts AS p -- use schema prefix! 
    INNER JOIN dbo.RPIv AS i -- use PROPER JOINS! 
     ON i.IVProduct = p.Productid 
    INNER JOIN dbo.RPTrsd AS d 
     ON i.UPC = d.UPC 
     AND i.StoreID = d.StoreID 
    INNER JOIN dbo.RPTrs AS s 
     ON s.StoreID = d.StoreID 
     AND s.ReceiptNO = d.ReceiptNO 
    WHERE s.TRSdate >= @trsfrom -- use strongly typed parameters! 
    AND s.TRSdate <= @trsto;'; 

EXEC sp_executesql @sql, 
    N'@trsfrom DATETIME, @trsto DATETIME', 
    @trsfrom, @trsto; 
----^^^^^^^^^^^^^^^^ here is how the query gets the @trsfrom & @trsto values 

我仍然認爲你一個##全局臨時表的使用是相當危險的。如果兩個人同時運行這些代碼,他們將會遇到嚴重的問題。

+0

我不是想說你錯了。我只在過去的兩個月裏一直與MsSQL合作,所以我仍然在努力學習正確的錯誤和不良習慣。你的答案正是我正在尋找的。非常感謝。只有幾個問題。用戶選擇網站上的日期作爲日期時間解析,查詢在哪裏查看此信息?在宣佈N'做什麼?以及2000年2代代表什麼?同樣,非常感謝你 – JohnZ 2013-02-28 15:53:28

+0

@JohnZ我在代碼中標記了日期時間參數如何傳遞到查詢中。您不需要轉換爲字符串並連接以傳入文字(取決於它們的使用方式) - 將它們作爲參數傳遞給sp_executesql([在此處爲更多內容](http://sqlblog.com/blogs) /aaron_bertrand/archive/2011/09/17/bad-habits-to-kick-using-exec-instead-of-sp-executesql.aspx))。 'N'前綴表示包含的字符串是Unicode,而sp_executesql則需要Unicode值。 '2,2000'意思是「從第二個字符開始,取2000個字符」 - 這會去掉前面的逗號。 – 2013-02-28 16:01:02

+0

你是先生,是一位了不起的人幫助我。我正在爲您的網站添加書籤,並將閱讀並希望從中學習。關於你的代碼的最後一個問題,所以我明白它做了什麼以及我能改變什麼'DATEADD(DAY,DATEDIFF(DAY,0,@ trsto),0)'DAY'和'0'做了什麼? – JohnZ 2013-02-28 16:11:48

相關問題