if @id is null
select
id
into #id
from table_info
else
select
if
into #id -- This shows : There is already an object name '#id' in the database.
from table_info i
where i.id=@id
这是我程序的第一部分,如果有id输入,它只会计算id的相关信息,如果没有,它会计算所有id。
我想我可以创建一个表并插入信息。有没有办法解决这个错误?
答案 0 :(得分:3)
这可以通过让WHERE子句进行所有检查来轻松完成:
select id
into #id
from table_info i
where @id is null or i.id = @id
答案 1 :(得分:0)
您也可以使用ISNULL
select id
into #id
from table_info i
where i.id = ISNULL(@id, i.id)
答案 2 :(得分:0)
正如您所说,您可以先显式创建表格,然后使用INSERT INTO
而不是SELECT INTO
:
CREATE TABLE #T (ID INT)
IF @id IS NULL
BEGIN
INSERT #T (ID)
SELECT ID
FROM table_info;
END
ELSE
BEGIN
INSERT #T (ID)
SELECT ID
FROM table_info
WHERE ID = @ID;
END
或者您可以使用UNION ALL
:
SELECT ID
INTO #T
FROM table_info
WHERE @ID IS NULL
UNION ALL
SELECT ID
FROM table_info
WHERE ID = @ID;
使用WHERE ID = @ID OR @ID IS NULL
发布的其他解决方案可行,但我会谨慎处理,因为根据您的数据,您最终可能会得到次优的执行计划。
一个非常简单的例子:
IF OBJECT_ID(N'tempdb..#table_info', 'U') IS NOT NULL DROP TABLE #Table_info;
CREATE TABLE #table_info (ID INT NOT NULL PRIMARY KEY, Filler CHAR(1));
INSERT #table_info (ID)
SELECT TOP 1000000 ROW_NUMBER() OVER(ORDER BY a.object_id)
FROM sys.all_objects a, sys.all_objects b;
现在,对于一些基准测试:
SELECT COUNT(Filler) FROM #table_info;
SELECT COUNT(Filler) FROM #table_info WHERE ID = 50000;
这给出了以下计划:
因此,如果我们指定一个ID,我们可以执行索引搜索而不是索引扫描,这要快得多(0%对100%)。
现在,参数测试:
DECLARE @SQL NVARCHAR(MAX) = 'SELECT COUNT(Filler) FROM #Table_info WHERE ID = @ID OR @ID IS NULL';
EXECUTE sp_executesql @SQL, N'@ID INT', 50000;
EXECUTE sp_executesql @SQL, N'@ID INT', NULL;
给出了:
问题在于,由于optmiser在编译时不知道@ID
是否为null或具有值,因此必须构建一个适用于两者的计划,因此无论哪种方式都使用聚集索引扫描速度慢得多。
如果我们使用IF
控制流程,就像在问题中一样,那么优化工具再次能够选择最佳计划:
DECLARE @SQL NVARCHAR(MAX) = 'IF @ID IS NULL
SELECT COUNT(Filler) FROM #Table_info;
ELSE
SELECT COUNT(Filler) FROM #Table_info WHERE ID = @ID;';
EXECUTE sp_executesql @SQL, N'@ID INT', 50000;
EXECUTE sp_executesql @SQL, N'@ID INT', NULL;
计划:
n.b。使用UNION
具有与此相同的效果,因为它是两个select语句,生成两个计划,两个都是最优的
您可以使用OPTION (RECOMPILE)
确保使用OR
根据参数的值获得最佳计划(并避免参数嗅探),因此有解决方法,您只需要解决哪种解决方案最适合您。我通常更喜欢明确地创建一个表,所以我通常倾向于这样做并保留你的IF
语句。