在SQL Server proc中,我们可以传入一个字符串值列表。有时这可能是一个空字符串。我们打破这个字符串(这是一个csv字符串)并将每个值存储在临时表中。同样,它可以是空白的,因此在这种情况下临时表是空的。
我们在where子句中尝试做的是让它针对临时表运行但是如果没有数据则针对所有内容运行它。有一个'技巧'我之前从未使用过的,并且不确定我是否完全理解其他人在工作中使用但是它不能用于此查询(它会杀死性能并且查询永远不会在4秒钟后返回)。
下面是一个示例查询,where部分是关键字:
DECLARE @myList AS NVARCHAR(MAX)
SET @myList = '73'
CREATE TABLE #TempList (data int)
INSERT INTO #TempList
SELECT * FROM BreakCSV(@myList,',')
DECLARE @Count int
SELECT @Count = COUNT(data) FROM #TempList sl WHERE ISNULL(sl.data,0) <> 0
SELECT *
FROM MyTable
WHERE MyDateField BETWEEN '1/1/2015' AND '3/1/2015'
AND (MyIdField IN (SELECT data FROM #TempList WHERE data <> 0) OR @Count = 0)
与@Count的OR部分是诀窍。如果TempList没有记录,那么@Count将等于0而0 = 0应该使它拉动整个表。但是,即使TempList中有记录,只要OR @Count = 0这一事实就会使查询无法返回。如果我注释掉@Count = 0,那么它会在4秒内按预期返回。
我很好奇是否有人可以解释这个思维过程中的逻辑,如果有一种不同的方法可以在没有IF语句的情况下执行此类操作,并且当您需要某些特定值时,只需使用不同的where子句复制此查询或者你想要它们而不必全部指定它们。另外,没有动态的sql。
答案 0 :(得分:1)
使用您的示例代码,这似乎是一种更好的优化方法。请记住 - 有时,更多代码 更好。
DECLARE @myList AS NVARCHAR(MAX)
DECLARE @Count int
SET @myList = '73'
CREATE TABLE #TempList (data int)
INSERT INTO #TempList
SELECT DISTINCT data
FROM BreakCSV(@myList,',')
WHERE data != 0
SET @Count = @@ROWCOUNT
CREATE UNIQUE INDEX ix1 ON #tempList(data)
IF @count = 0
SELECT *
FROM MyTable
WHERE MyDateField BETWEEN '1/1/2015' AND '3/1/2015'
ELSE
SELECT *
FROM MyTable
INNER JOIN #TempList
ON MyIdField = data
WHERE MyDateField BETWEEN '1/1/2015' AND '3/1/2015'
答案 1 :(得分:0)
你过度设计了这个。摆脱这个:
DECLARE @Count int
SELECT @Count = COUNT(data) FROM #TempList sl WHERE ISNULL(sl.data,0) <> 0
改变这个:
AND (MyIdField IN (SELECT data FROM #TempList WHERE data <> 0) OR @Count = 0)
到此:
AND (MyIdField IN (SELECT data FROM #TempList WHERE data <> 0) OR @myList is null)
使用可选参数编写存储过程时,这是一种常见方法。