2013-02-28 75 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

相关问题