问题
I'm trying to build an SQL query with given params, but I get a weird error and cant understand why. Here is my SP and result
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
And the error is
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.
Can you describe the error? Thanks!
回答1:
Cast
the numeric values i.e. @PriceMin , @PriceMax and @CityID before concatenating in sql statement.
Modified sql statement is as per below:
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) )
回答2:
Romil's answer solves the problem you asked, but what you should be asking is how to change this query to not be dynamic. I don't know your DB structure so this query will need to be verified but the WHERE clause updates I made will allow your query to run without being dynamic. This will increase performance dramatically, reduce injection exposure, and is all around the better way to go about these types of queries.
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
I would make further improvements to move those sub-queries into JOIN statements combined with GROUP BY statements to improve performance, but that would require further DB knowledge.
来源:https://stackoverflow.com/questions/15067472/dynamic-sql-query-search