我需要帮助来解决复杂的SQL查询。我试图一次建立一个vlock的查询。 一个问题是:如果@PubNum的参数为NULL,则查询显示“..... where PubNum ='”这是一个问题。我需要的是如果参数为NULL,那么PubNum不应该在where子句中。
第二个问题是:
有什么想法吗?
完整的查询是:
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)
答案 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