我有一个存储过程,我将产品类型(prod_type)作为参数传递最多四次。这些参数中的每一个都可能为空,在这种情况下应忽略它们。他们应该在每种产品类型之间使用OR运算符,以便我们收集所有要求的产品类型。
如果可能的话,我想避免使用通过sp_ExecuteSQL传递的动态SQL(我知道这很容易)。
我正在尝试做的简化的,孤立的版本在下面讨论:
CREATE TABLE #Products (Prod_ID int, prod_type int);
INSERT INTO #Products
SELECT 1, 2
UNION ALL
SELECT 2, 3
UNION ALL
SELECT 3, 3
UNION ALL
SELECT 4, 1
UNION ALL
SELECT 4, 5
DECLARE @prod_type1 as int;
DECLARE @prod_type2 as int;
DECLARE @prod_type3 as int;
DECLARE @prod_type4 as int;
SET @prod_type1 = NULL;
SET @prod_type2 = 2;
SET @prod_type3 = NULL;
SET @prod_type4 = 3;
Select * from #Products
WHERE ((prod_type = ISNULL(@prod_type1,prod_type))
OR (prod_type = ISNULL(@prod_type2,prod_type))
OR (prod_type = ISNULL(@prod_type3,prod_type)
OR (prod_type = ISNULL(@prod_type4,prod_type))))
我希望执行的内容是:
Select * from [Product].[Product]
WHERE (prod_type = 2 OR prod_type = 3)
显然,使用ISNULL的上述解决方法将无效,因为ISNULL方法会将每行的产品类型与自身进行比较,从而产生积极的“点击”。 COALESCE会遇到同样的问题。
有人可以建议一个不涉及使用sp_ExecuteSQL的解决方案吗?
答案 0 :(得分:1)
试试这个:
DECLARE @ProdTypes TABLE (Prod_Type INT NOT NULL);
INSERT INTO @ProdTypes (Prod_Type) VALUES (2);
INSERT INTO @ProdTypes (Prod_Type) VALUES (3);
SELECT pr.*
FROM #Products pr
WHERE EXISTS (SELECT 1
FROM @ProdTypes pt
WHERE pt.Prod_Type = pr.Prod_Type);
使用EXISTS
可以在逻辑上允许OR
条件。如果找到匹配项,EXISTS
将退出,因此它不会遍历@ProdTypes中的所有行,除非:
但很多时候它会在扫描整个表变量之前退出。
修改强>
此外,您不应该将多个@Prod_TypeX参数传递给您的过程。相反,传入Ints的CSV列表并使用基于SQLCLR或XML的字符串拆分器将其插入到表变量中,如:
INSERT INTO @ProdTypes (Prod_Type)
SELECT CONVERT(INT, csv.SplitVal)
FROM dbo.SQLCLRorXMLbasedSplitter(@ProdTypesCSV) csv;
答案 1 :(得分:0)
尝试像这样更改你Where Clause
。
Select *
from
#Products
WHERE prod_type in(@prod_type1,@prod_type2,@prod_type2,@prod_type4)