0

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

你能描述一下错误吗?谢谢!

4

2 回答 2

1

Cast在 sql 语句中连接之前的数值,即 @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) )
于 2013-02-25T13:07:18.357 回答
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

我将进一步改进将这些子查询移动到 JOIN 语句中并结合 GROUP BY 语句来提高性能,但这需要进一步的数据库知识。

于 2013-02-26T07:31:45.937 回答