我正在尝试使用给定的参数构建SQL查询,但是我得到了一个奇怪的错误并且无法理解为什么。这是我的SP和结果
ALTER PROCEDURE [dbo].[sp_Photographers_Select_Search]
@Date varchar(100),
@PriceMin int,
@PriceMax int,
@CityID int
AS
BEGIN
SET DATEFORMAT DMY
DECLARE @SQL as varchar(2000)
SET @SQL = 'SELECT *,
(SELECT TOP (1) Price FROM Packages WHERE PhotographerID = Photographers.PhotographerID ORDER BY Price) as PriceMin,
(SELECT TOP (1) Price FROM Packages WHERE PhotographerID = Photographers.PhotographerID ORDER BY Price DESC) as PriceMax,
(SELECT COUNT(GalleryID) FROM Galleries WHERE PhotographerID = Photographers.PhotographerID AND Status = 1) as GalleryCount,
(SELECT COUNT(CommentID) FROM Comments WHERE ContentID = Photographers.PhotographerID AND Status = 1 AND TypeID = 1) as CommentCount
FROM Photographers WHERE 1 = 1 '
IF @PriceMin <> 0 OR @PriceMax <> 0 BEGIN
SET @SQL = @SQL + ' AND PhotographerID IN(SELECT PhotographerID FROM Packages WHERE Price BETWEEN '+@PriceMin+' AND '+@PriceMax+') '
END
IF @CityID > 0
SET @SQL += ' AND CityID = '+@CityID+''
SET @SQL = @SQL + ' AND PhotographerID NOT IN (SELECT PhotographerID FROM Appointments WHERE Date = '''+@Date+''')'
EXEC (@SQL)
END
EXEC @return_value = [dbo].[sp_Photographers_Select_Search]
@Date = N'23.05.2013',
@PriceMin = 0,
@PriceMax = 0,
@CityID = 34
错误是
Msg 245, Level 16, State 1, Procedure sp_Photographers_Select_Search, Line 23
Conversion failed when converting the varchar value 'SELECT *,
(SELECT TOP (1) Price FROM Packages WHERE PhotographerID = Photographers.PhotographerID ORDER BY Price) as PriceMin,
(SELECT TOP (1) Price FROM Packages WHERE PhotographerID = Photographers.PhotographerID ORDER BY Price DESC) as PriceMax,
(SELECT COUNT(GalleryID) FROM Galleries WHERE PhotographerID = Photographers.PhotographerID AND Status = 1) as GalleryCount,
(SELECT COUNT(CommentID) FROM Comments WHERE ContentID = Photographers.PhotographerID AND Status = 1 AND TypeID = 1) as CommentCount
FROM Photographers WHERE 1 = 1 ' to data type int.
你能描述错误吗?谢谢!
答案 0 :(得分:1)
Cast
数值,即@ PriceMin,@ PriceMax和@CityID。
修改后的sql语句如下:
IF @PriceMin <> 0 OR @PriceMax <> 0
BEGIN
SET @SQL = @SQL + ' AND PhotographerID IN(SELECT PhotographerID FROM Packages WHERE Price BETWEEN '+ cast(@PriceMin as varchar(10))
+' AND '+ cast(@PriceMax as varchar(10)) +') '
END
IF @CityID > 0
SET @SQL += ' AND CityID = '+ cast(@CityID as varchar(10) )
答案 1 :(得分:1)
Romil的答案解决了您提出的问题,但您应该问的是如何将此查询更改为不动态。我不知道您的数据库结构,因此需要验证此查询,但我所做的WHERE子句更新将允许您的查询在不动态的情况下运行。这将显着提高性能,减少注射暴露,并且是处理这些类型查询的更好方法。
ALTER PROCEDURE [dbo].[sp_Photographers_Select_Search]
@Date AS VARCHAR(100),
@PriceMin AS INT,
@PriceMax AS INT,
@CityID AS INT
AS
BEGIN
SET DATEFORMAT DMY
SELECT *,
(SELECT TOP (1) Price FROM Packages WHERE PhotographerID = Photographers.PhotographerID ORDER BY Price) AS PriceMin,
(SELECT TOP (1) Price FROM Packages WHERE PhotographerID = Photographers.PhotographerID ORDER BY Price DESC) AS PriceMax,
(SELECT COUNT(GalleryID) FROM Galleries WHERE PhotographerID = Photographers.PhotographerID AND Status = 1) AS GalleryCount,
(SELECT COUNT(CommentID) FROM Comments WHERE ContentID = Photographers.PhotographerID AND Status = 1 AND TypeID = 1) AS CommentCount
FROM Photographers
WHERE 1 = 1
AND PhotographerID NOT IN (SELECT PhotographerID FROM Appointments WHERE Date = @Date)
AND
(
(
@PriceMin = 0
AND @PriceMax = 0
)
OR PhotographerID IN (SELECT PhotographerID FROM Packages WHERE Price BETWEEN @PriceMin AND @PriceMax)
)
AND
(
@CityID = 0
OR CityID = @CityID
)
END
我会进一步改进将这些子查询移动到与GROUP BY语句结合使用的JOIN语句中以提高性能,但这需要进一步的数据库知识。