复杂的动态SQL查询

时间:2010-06-24 14:13:28

标签: tsql stored-procedures

我需要帮助来解决复杂的SQL查询。我试图一次建立一个vlock的查询。 一个问题是:如果@PubNum的参数为NULL,则查询显示“..... where PubNum ='”这是一个问题。我需要的是如果参数为NULL,那么PubNum不应该在where子句中。

第二个问题是

  • 如果@StartDate不为NULL并且@EndDate不为NULL,那么在@StartDate和@EndDate之间的RecAddDate
  • 如果@StartDate不为NULL且@EndDate为空,那么@StartDate与今天之间的RecAddDate
  • 如果@StartDate为空并且@EndDate不为NULL那么RecAddDate BETWEEN '01 / 01/2000'和@EndDate
  • 如果@StartDate为空并且@EndDate为空那么RecAddDate BETWEEN '01 / 01/2000'和今天

有什么想法吗?

完整的查询是:

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
ALTER PROCEDURE [dbo].[usp_BookItemSearch]
    @BookSKU varchar(30) = NULL
    ,@SearchType int = NULL
    ,@PubNum varchar(10) = NULL
    ,@UserID int = NULL
    ,@StartDate smalldatetime = NULL
    ,@EndDate smalldatetime = NULL
AS
DECLARE @SQL as varchar(4000)

SET @SQL = 'SELECT RecID, PubNum, VendorName, InvoiceNum, BookSKU, RecAddDate FROM tb_BookInventoryLog]'

IF @BookSKU IS NOT NULL
    BEGIN
        IF  @SearchType = 2
            BEGIN
                SET @SQLClause = ' WHERE BookSKU LIKE ''%' + @BookSKU + ''''    --Ends with
            END
        IF  @SearchType = 1
            BEGIN
                SET @SQLClause = ' WHERE BookSKU LIKE ''%' + @BookSKU + '%'''   --Contains
            END
        IF  @SearchType = 0
            BEGIN
                SET @SQLClause = ' WHERE BookSKU LIKE ''' + @BookSKU + '%'''    --Starts with
            END
    END

IF @PubNum IS NOT NULL
    BEGIN
        IF @SQLClause IS NOT NULL
            BEGIN
                SET @SQLClause = @SQLClause + ' AND PubNum = ''' + @PubNum + ''''
            END
        ELSE
            BEGIN
                SET @SQLClause = @SQLClause + ' WHERE PubNum = ''' + @PubNum + ''''
            END
    END

IF @UserID IS NOT NULL 
    BEGIN
        IF @SQLClause IS NOT NULL
            BEGIN
                SET @SQLClause = @SQLClause + ' AND (UserID = ' + CAST(@UserID AS VarChar) + ')'
            END
        ELSE
            BEGIN
                SET @SQLClause = @SQLClause + ' WHERE (UserID = ' + CAST(@UserID AS VarChar) + ')'
            END
    END

If (@StartDate Is Not Null) AND (@EndDate Is Not Null)
    BEGIN
            Set @SQLClause = @SQLClause + ' And (JoiningDate BETWEEN @StartDate AND @EndDate)'
    END

IF (@EndDate IS NOT NULL)
    BEGIN
        IF (@StartDate IS NOT NULL) 
            BEGIN
                SET @SQL = @SQL +  ' WHERE RecAddDate between' + CAST(@StartDate As smalldatetime) + ' AND ' + CAST(@EndDate as smalldatetime) + ''
            END
        ELSE
            BEGIN
                SET @SQL = @SQL +  ' RecAddDate BETWEEN 01/01/2000 AND @EndDate + '
            END
    END

SET @SQL = @SQL + @SQLClause + ' ORDER BY BookSKU, PubNum'
PRINT @SQL
--EXECUTE (@SQL)

3 个答案:

答案 0 :(得分:4)

您可以使用参数和一些NULL检查作为WHERE子句的一部分,使用几种不同的技术,而不是动态SQL(它引入了大量问题,而实际上并不是必需的)。在你想要做什么。我使用SQL 2000/2005进行了测试,它运行正常(我还假设它在2008 / R2中没问题)。

ALTER PROCEDURE [dbo].[usp_BookItemSearch]
    @BookSKU varchar(30) = NULL
    ,@SearchType int = NULL
    ,@PubNum varchar(10) = NULL
    ,@UserID int = NULL
    ,@StartDate smalldatetime = NULL
    ,@EndDate smalldatetime = NULL
AS


  SELECT RecID, PubNum, VendorName, InvoiceNum, BookSKU, RecAddDate
    FROM [tb_BookInventoryLog]
   WHERE (
          (@BookSKU IS NULL) OR 
          (BookSKU LIKE CASE @SearchType
                          WHEN 0 THEN       @BookSKU + '%'
                          WHEN 1 THEN '%' + @BookSKU + '%'
                          WHEN 2 THEN '%' + @BookSKU
                        END
          )
         )
     AND ISNULL(@PubNum, PubNum) = PubNum
     AND ISNULL(CAST(@UserID AS VARCHAR), UserID) = UserID
     AND (
          (@StartDate IS NULL OR @EndDate IS NULL) OR
          (JoiningDate BETWEEN @StartDate AND @EndDate)
         )
     AND RecAddDate BETWEEN CASE
                              WHEN @EndDate IS NULL THEN RecAddDate
                              ELSE ISNULL(@StartDate, '01/01/2000')
                            END
                        AND ISNULL(@EndDate, GETDATE())
ORDER BY BookSKU, PubNum

答案 1 :(得分:1)

如果没有null,我会有条件地包含过滤器。这样的事情: -

Set @WhereClause = 'Where 1=1'
If @PubNum is not null
  Set @WhereClause = @WhereClause + ' AND PubNum = ''' + @PubNum + ''''

答案 2 :(得分:0)

第二期:

  

(@ StartDate不显示参数的值,而是显示“..... StartDate = @StartDate .....”)

如果您希望继续使用动态SQL,请考虑使用sp_executesql替换EXECUTE。该存储过程将接受您可以在动态SQL(参数替换)中使用的参数。例如:

Set @SQLClause = @SQLClause + ' And (JoiningDate BETWEEN @StartDate_PARAM AND @EndDate_PARAM)'

对于上述内容,请将@EndDate_PARAM添加为如下参数:

exec sp_executesql @SQL, N'@StartDate_PARAM DateTime, @EndDate_PARAM DateTime', @StartDate_PARAM = @StartDate, @EndDate_PARAM = @EndDate

一开始看起来有点奇怪,但如果你要使用动态SQL路径,这是一件好事。

您可以在此处找到有关此内容的更多信息:http://msdn.microsoft.com/en-us/library/ms175170.aspx