Сложный динамический SQL-запрос - PullRequest
1 голос
/ 24 июня 2010

Мне нужна помощь в разрешении сложного запроса SQL. Я пытаюсь создать запрос по одному vlock за раз. Одна проблема - : если параметр для @PubNum имеет значение NULL, запрос показывает "..... где PubNum = '', что является проблемой. Что мне нужно, если параметр имеет значение NULL, то PubNum не должно быть в предложении where.

Второй выпуск - :

  • Если @StartDate NOT NULL и @EndDate NOT NULL THEN, то RecAddDate МЕЖДУ @StartDate AND @ EndDate
  • Если @StartDate NOT NULL и @EndDate равен NULL, то RecAddDate МЕЖДУ @StartDate AND Today
  • Если @StartDate равен NULL и @EndDate не равен NULL, то RecAddDate МЕЖДУ '01 / 01/2000 'И @ EndDate
  • Если @StartDate равен NULL и @EndDate равен NULL, то RecAddDate МЕЖДУ '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 ]

4 голосов
/ 24 июня 2010

Вместо того, чтобы делать динамический SQL (который создает целый ряд проблем, и часто фактически не требуется), вы можете просто использовать параметры и некоторые проверки NULL как часть вашего предложения WHERE, используя несколько различных методов, в зависимости отна то, что вы пытаетесь сделать.Я проверил это с помощью 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 голос
/ 24 июня 2010

Я бы условно включил фильтры, если бы они не были нулевыми.Как то так: -

Set @WhereClause = 'Where 1=1'
If @PubNum is not null
  Set @WhereClause = @WhereClause + ' AND PubNum = ''' + @PubNum + ''''
0 голосов
/ 24 июня 2010

Для вашего второго выпуска:

(@ StartDate не отображает значение параметра, вместо этого отображается «..... StartDate = @StartDate .....»)

Если вы хотите продолжать использовать динамический SQL, рассмотрите возможность замены EXECUTE на sp_executesql.Эта хранимая процедура будет принимать параметры, которые вы затем сможете использовать внутри своего динамического 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...