动态SQL查询搜索

时间:2013-02-25 12:54:38

标签: sql sql-server dynamic-sql

我正在尝试使用给定的参数构建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.

你能描述错误吗?谢谢!

2 个答案:

答案 0 :(得分:1)

在pql语句中连接之前,

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语句中以提高性能,但这需要进一步的数据库知识。