我在SQL Server 2008中创建存储过程。主查询的WHERE
子句可能是
WHERE (MyTable.Code = 'A')
或
WHERE (MyTable.Code <> 'A')
问题:处理此问题的最简单方法是什么?有一个输入参数,告诉使用哪个条件然后使用if语句使用第一个SQL语句,否则第二个?看起来不是最有效的方式。
另外,有没有办法将整个WHERE
子句作为输入参数传递?
示例参数
@WHERE: "WHERE (MyTable.Code='A')
这样你就可以......
SELECT * FROM TABLE @WHERE
答案 0 :(得分:3)
最简单的路线是有额外的参数来决定以下列方式使用哪一个。唯一的问题是,当你开始这样做时,你最终会得到糟糕的执行计划。
DECLARE @Bit BIT = 0;
SELECT *
FROM dbo.MyTable AS m
WHERE (m.Code <> 'A' AND @Bit = 0)
OR (m.Code = 'A' AND @Bit = 1)
为了避免错误的执行计划,您有几种不同的选择。
您可以在Parameter Sniffing Problem and Possible Workarounds
了解更多相关信息在您的情况下,最简单的方法是使用局部变量。
例如:
CREATE PROC dbo.GetSomeData (@pBit BIT)
AS
BEGIN
DECLARE @Bit BIT = @pBit;
SELECT *
FROM dbo.MyTable AS m
WHERE (m.Code <> 'A' AND @Bit = 0)
OR (m.Code = 'A' AND @Bit = 1)
END
答案 1 :(得分:1)
在存储过程中使用if语句来决定两个查询之间(在我看来)比将where子句作为参数传递更好。如果将where子句作为参数传递,那么数据库的逻辑就会泄漏到上面的层中。另外,根据您在上面构建图层的方式,您可以打开自己的SQL注入攻击。
虽然看起来它们是两个不同的查询,所以这可能更适合作为两个存储过程,然后在你的调用代码中决定要调用哪一个。
答案 2 :(得分:1)
如果您正在寻找快速简便的方法,可以使用标志(或任何条件决定使用哪个WHERE子句)并将它们组合成一个WHERE子句。
WHERE (@flag = 1 AND code = 'A') OR (@flag = 0 AND code <> 'A')
对于更高级的SQL,您可以使用dynamic sql。
答案 3 :(得分:0)
你可能使用动态SQL,但在这种情况下,没有必要。只需使用条件WHERE子句:
CREATE PROCEDURE ...
(@IsA bit)
AS
SELECT ...
WHERE (@IsA = 1 AND MyTable.Code='A')
OR (@IsA = 0 AND MyTable.Code<>'A')
有没有办法将整个WHERE子句作为输入参数传递?
嗯,当然,您可以将其作为字符串传递,但这样做有很多风险:
答案 4 :(得分:0)
如果您的输入参数是布尔值,或任何相关的东西,您可以执行以下操作:
SELECT *
FROM MyTable
WHERE (MyTable.Code='A' AND MyParameter='Equals')
OR (My.Table.Code <> 'A' AND MyParementer='NotEqual')
我过去曾使用类似的东西来实现这一目标。
答案 5 :(得分:0)
我建议使用一个参数来指示将使用哪个WHERE子句。
假设您有一个名为@WhereClauseToUse的参数。
你可以这样:
select *
from table
where (@WhereClauseToUse = 1 and Code = 'A')
or (@WhereClauseToUse = 2 and Code <> 'A')
答案 6 :(得分:0)
我在WHERE子句中使用了条件,比如
-- @A = 1/true, then WHERE (MyTable.Code = 'A')
-- @A = 0/false, then WHERE (MyTable.Code <> 'A')
declare @A bit
WHERE ((MyTable.Code = 'A' and @A = 1) OR (MyTable.Code <> 'A' and @A = 0))