2013-02-25 187 views
0

我想建立一個SQL查詢與給定的參數,但我得到一個奇怪的錯誤,不能理解爲什麼。這是我的SP,並導致動態SQL查詢搜索

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 '[email protected]+' AND '[email protected]+') ' 
    END 

    IF @CityID > 0 
     SET @SQL += ' AND CityID = '[email protected]+'' 

    SET @SQL = @SQL + ' AND PhotographerID NOT IN (SELECT PhotographerID FROM Appointments WHERE Date = '''[email protected]+''')'  

    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

什麼類型是STATUS列的? – veljasije 2013-02-25 12:59:05

+0

這是smallint,但錯誤行IF IF CityID> 0 SET @SQL + ='AND CityID ='+ CityID +'' – 2013-02-25 13:02:04

回答

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)) 
+0

謝謝,救了我的一天。 – 2013-02-25 13:09:54

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聯合聲明,以提高性能,但這需要進一步DB知識。