3

我试图将整个存储过程作为字符串执行,因为我必须使条件动态化。这是我的代码:

CREATE PROCEDURE SP1
  (@VoucherType varchar(10),
  @ProductID bigint,
  @BrandID bigint)
AS
BEGIN

DECLARE @Condition as varchar(300)
SET @Condition=' WHERE VoucherType=@VoucherType '
IF (@ProductID<>-1)
  BEGIN
  SET @Condition=@Condition+' AND ProductID='+cast(@ProductID as varchar)
  END
IF (BrandID<>-1)
  BEGIN
  SET @Condition=@Condition+' AND BrandID='+cast(@BrandID as varchar)
  END
EXEC('SELECT * FROM Products '+@Condition)

END

过滤ProductIDBrandID是可选的(如果它们的值不是 -1,那么这些条件将添加到 where 子句)。并且按 VoucherType 过滤是强制性的。问题是我无法@VoucherType在线获取参数的值:

SET @Condition=' WHERE VoucherType=@VoucherType '

错误说没有名为 SI 的列(这是我的输入@VoucherType)。如何获取该参数的值。

4

4 回答 4

1

无需动态 SQL 即可:

SELECT * FROM Products WHERE VoucherType=@VoucherType AND 
  (@ProductID=-1 OR  ProductID=@ProductID)
  AND 
  (@BrandID=-1 OR  BrandID=@BrandID)
于 2013-11-12T13:02:25.507 回答
1

如果逻辑如您所描述,则可以在没有动态 SQL 的情况下执行此操作 - 只需通过与每个参数的默认值进行比较来直接在 where 子句中使用参数(基本上使 where 子句的该部分成为 no-op if这些值是您用来表示“不过滤”的值)。

CREATE PROCEDURE Sp1
(
  @VoucherType VARCHAR(10),
  @ProductID   BIGINT,
  @BrandID     BIGINT
)
AS
  BEGIN
      SELECT *
      FROM   Products
      WHERE  (@VoucherType IS NULL OR VoucherType = @VoucherType)
             AND (@ProductID = -1 OR ProductID = @ProductID)
             AND (@BrandID = -1 OR BrandID = @BrandID)
  END

请注意,您可能应该只选择您需要的列,而不是*

(如果您不希望 VoucherType 像我在这里所做的那样是可选的,只需删除 NULL 比较)

于 2013-11-12T13:02:36.790 回答
1

为什么它不起作用?因为您正在尝试使用该参数。你需要改变这个:

SET @Condition=' WHERE VoucherType=@VoucherType '

对此:

SET @Condition=' WHERE VoucherType='' ' + @VoucherType + ''''

注意:您实际上可以在没有动态 SQL 的情况下执行此操作。考虑以下语句:

SELECT * FROM Products
WHERE (VoucherType = @VoucherType) AND
    (@ProductID = -1 OR ProductID = @ProductID) AND
    (@BrandID = -1 OR BrandID = @BrandID
于 2013-11-12T13:03:26.943 回答
0

使用 sp_executesql,它接收 3 个参数:查询、参数类型和参数值:

仅适用于 @VoucherType 参数的简短示例:

EXEC sp_executesql N'SELECT * FROM Products WHERE VoucherType = @VoucherType',
N'@VoucherType VARCHAR(10)',
@VoucherType = @VoucherType

然后您应该对 ProductID 和 BrandID 执行相同的技巧。

其他建议:

1/ 使用 NULL 而不是 -1 并检查 NULL:

IF BrandID IS NOT NULL

2/ 根据您的物理设计,您可以在没有 sp_executesql 的情况下重写您的语句

SELECT * FROM Products
WHERE VoucherType=@VoucherType
AND @ProductID IS NULL OR ProductID = @ProductID
AND @BrandID IS NULL OR BrandID = @BrandID
于 2013-11-12T13:03:05.517 回答