Sql错误必须声明标量变量,即使在声明变量之后也是如此

时间:2013-02-01 07:31:16

标签: .net sql sql-server-2008 tsql

即使我使用Must declare the scalar variable "@collectionId"

,我的查询如下并收到错误[GetAllProductById] 6,0,0,0,'A122'
ALTER proc [dbo].[GetAllProductById] 
(
    @collectionId int,
    @GrandId int  ,
    @ParentId int ,
    @ChildId int,
    @dealerid varchar(50) 
)
As
Begin

Declare @sql as varchar(max)
 -- In case dealer is logged in ,then calculate the Discounted amount and return the same,
    -- else return Mrp and Our Price for all other customers

    IF  @collectionid<=0

        BEGIN
            IF @dealerid<>''
                BEGIN
                    SET @sql = '    Select Top(5) Product.Id,ProdImage,ProductCode, ProductName,MrpPrice, BasicPrice,ValueAdd, Price =ISNULL((Product.BasicPrice + ValueAdd),0), 
                                          Discounted = ISNULL((Select (Product.BasicPrice + (ValueAdd -(ValueAdd *(Discount*0.01))))
                                                 From DealerDiscount 
                                                 Where CategoryId = Product.GrandCategoryId AND DealerId='+@dealerid+'),0)
                                    From Product  Where 1=1 ';
                END
             ELSE
                BEGIN
                    SET @sql = '    Select Top(5) Id,ProdImage,ProductCode, ProductName,MrpPrice, BasicPrice,ValueAdd, Price =ISNULL((BasicPrice + ValueAdd),0), Discounted=0 
                                    From Product
                                    Where 1=1 ';
                END 

        END
    ELSE
        BEGIN
            IF @dealerid<>''
                BEGIN
                    SET @sql = '    Select  Product.Id,ProdImage,ProductCode,Collections.Name,Collections.Id, ProductName,MrpPrice, BasicPrice,ValueAdd, Price =ISNULL((Product.BasicPrice + ValueAdd),0), 
                                          Discounted = ISNULL((Select (Product.BasicPrice + (ValueAdd -(ValueAdd *(Discount*0.01))))
                                                 From DealerDiscount 
                                                 Where CategoryId = Product.GrandCategoryId AND DealerId='+@dealerid+'),0)
                                    FROM    Collections INNER JOIN
                                            Product ON Collections.Id = Product.CollectionId 
                                            where Product.CollectionId=@collectionId   AND 1=1 ';
                END
             ELSE
                BEGIN
                    SET @sql = '    Select  Product.Id,ProdImage,Collections.Name,Collections.Id,ProductCode, ProductName,MrpPrice, BasicPrice,ValueAdd, Price =ISNULL((BasicPrice + ValueAdd),0), Discounted=0 
                                    FROM    Collections INNER JOIN
                                            Product ON Collections.Id = Product.CollectionId 
                                            where Product.CollectionId=@collectionId AND 1=1 ';
                END 

            if (@GrandId > 0 and @ParentId>0 and @ChildId > 0 and @collectionId=0)
                Begin
                    Set @sql  = @sql + ' Product.ParentCategoryId = '+ Convert(Varchar, @ParentId)+' AND Product.GrandCategoryId = '+ Convert(Varchar, @GrandId)+' AND Product.ChitdCategoryId = '+Convert(varchar,@ChildId);
                End
            if (@GrandId > 0 and @ParentId>0 and @ChildId = 0 and @collectionId=0)
                Begin
                    Set @sql  = @sql + ' Product.ParentCategoryId = '+ Convert(Varchar, @ParentId)+' AND Product.GrandCategoryId = '+ Convert(Varchar, @GrandId)
                End
            if (@GrandId > 0 and @ParentId=0 and @ChildId = 0 and @collectionId=0)
                Begin
                    Set @sql  = @sql + ' AND Product.GrandCategoryId = '+ Convert(Varchar, @GrandId)
                End
        END

        exec(@sql)

END   

2 个答案:

答案 0 :(得分:1)

不是将值连接到TSQL,而是应该修改当前代码以在生成的TSQL中使用sp_executesql参数,这样可以避免在生成的TSQL中注入SQL的风险,并允许查询计划重复使用。例如:

SET @sql = '    Select Top(5) Product.Id,ProdImage,ProductCode, ProductName,MrpPrice, BasicPrice,ValueAdd, Price =ISNULL((Product.BasicPrice + ValueAdd),0), 
                                          Discounted = ISNULL((Select (Product.BasicPrice + (ValueAdd -(ValueAdd *(Discount*0.01))))
                                                 From DealerDiscount 
                                                 Where CategoryId = Product.GrandCategoryId AND DealerId=@dealerid),0)
                                    From Product  Where 1=1 ';
....
if (@GrandId > 0 and @ParentId>0 and @ChildId = 0 and @collectionId=0)
                Begin
                    Set @sql  = @sql + ' AND Product.ParentCategoryId = @ParentId AND Product.GrandCategoryId = @GrandId '
                End

请特别注意,我没有将当前参数值连接到生成的SQL中。

然后将其称为:

exec sp_executesql @sql, N'@dealerid int, @GrandId int',
                         @dealerid, @GrandId
                      -- ^^^ todo: add every parameter you need

第一个参数是TSQL;第二个参数(N'@dealerid int, @GrandId int')是通过标准SQL语法描述参数的aliteral,然后我们映射要使用的值。在这种情况下,为方便起见,我们使用相同的名称 - 但这不是必需的。

答案 1 :(得分:0)

在构建查询时,您需要将变量附加为字符串而不是仅仅分配。 请尝试:

ALTER proc [dbo].[GetAllProductById] 
(
    @collectionId int,
    @GrandId int  ,
    @ParentId int ,
    @ChildId int,
    @dealerid varchar(50) 
)
As
Begin

Declare @sql as varchar(max)
 -- In case dealer is logged in ,then calculate the Discounted amount and return the same,
    -- else return Mrp and Our Price for all other customers

    IF  @collectionid<=0

        BEGIN
            IF @dealerid<>''
                BEGIN
                    SET @sql = '    Select Top(5) Product.Id,ProdImage,ProductCode, ProductName,MrpPrice, BasicPrice,ValueAdd, Price =ISNULL((Product.BasicPrice + ValueAdd),0), 
                                          Discounted = ISNULL((Select (Product.BasicPrice + (ValueAdd -(ValueAdd *(Discount*0.01))))
                                                 From DealerDiscount 
                                                 Where CategoryId = Product.GrandCategoryId AND DealerId='+@dealerid+'),0)
                                    From Product  Where 1=1 ';
                END
             ELSE
                BEGIN
                    SET @sql = '    Select Top(5) Id,ProdImage,ProductCode, ProductName,MrpPrice, BasicPrice,ValueAdd, Price =ISNULL((BasicPrice + ValueAdd),0), Discounted=0 
                                    From Product
                                    Where 1=1 ';
                END 

        END
    ELSE
        BEGIN
            IF @dealerid<>''
                BEGIN
                    SET @sql = '    Select  Product.Id,ProdImage,ProductCode,Collections.Name,Collections.Id, ProductName,MrpPrice, BasicPrice,ValueAdd, Price =ISNULL((Product.BasicPrice + ValueAdd),0), 
                                          Discounted = ISNULL((Select (Product.BasicPrice + (ValueAdd -(ValueAdd *(Discount*0.01))))
                                                 From DealerDiscount 
                                                 Where CategoryId = Product.GrandCategoryId AND DealerId='+@dealerid+'),0)
                                    FROM    Collections INNER JOIN
                                            Product ON Collections.Id = Product.CollectionId 
                                            where Product.CollectionId='+CAST(NVARCHAR(50), @collectionId)+'   AND 1=1 ';
                END
             ELSE
                BEGIN
                    SET @sql = '    Select  Product.Id,ProdImage,Collections.Name,Collections.Id,ProductCode, ProductName,MrpPrice, BasicPrice,ValueAdd, Price =ISNULL((BasicPrice + ValueAdd),0), Discounted=0 
                                    FROM    Collections INNER JOIN
                                            Product ON Collections.Id = Product.CollectionId 
                                            where Product.CollectionId='+CAST(NVARCHAR(50), @collectionId)+' AND 1=1 ';
                END 

            if (@GrandId > 0 and @ParentId>0 and @ChildId > 0 and @collectionId=0)
                Begin
                    Set @sql  = @sql + ' Product.ParentCategoryId = '+ Convert(Varchar, @ParentId)+' AND Product.GrandCategoryId = '+ Convert(Varchar, @GrandId)+' AND Product.ChitdCategoryId = '+Convert(varchar,@ChildId);
                End
            if (@GrandId > 0 and @ParentId>0 and @ChildId = 0 and @collectionId=0)
                Begin
                    Set @sql  = @sql + ' Product.ParentCategoryId = '+ Convert(Varchar, @ParentId)+' AND Product.GrandCategoryId = '+ Convert(Varchar, @GrandId)
                End
            if (@GrandId > 0 and @ParentId=0 and @ChildId = 0 and @collectionId=0)
                Begin
                    Set @sql  = @sql + ' AND Product.GrandCategoryId = '+ Convert(Varchar, @GrandId)
                End
        END

        exec(@sql)

END