我有一个存储过程,我必须在其中连接10个表并使用WHERE
条件根据存储过程中传递的参数过滤记录。例如:
create procedure proc1
@var1 varchar(100) = null,
@var2 varchar(100) = null,
@var3 varchar(100) = null,
@var4 varchar(100) = null,
........
@var10 varchar(100) = null
as
begin
insert into #a
select * from
(
select * from
tab1 as a
inner join tab2 as b on a.rollnumber = b.rollnumber
inner join tab3 as c on c.city = b.city
........
inner join tab10 as j on J.id = i.id
where
a.id = isnull(@var1,a.id) and
b.id = isnull(@var2,b.id) and
c.id = isnull(@var3,c.id) and
...........
J.id = isnull(@var10,j.id)
) as abc
if (select count(*) from #a) < 10
begin
select * from #a
end
else
begin
print 'Cannot display the records as count is more than 10'
end
end
上面的存储过程工作正常,但它很慢,因为WHERE
子句中有10个条件。我想要的是如果没有向存储过程提供某些参数,则跳过该条件。例如,如果只将3个参数传递给存储过程,则WHERE
子句应跳过WHERE
子句中的其余参数。这将使程序更有效。因此,如果未传递@var1
,则应返回a.id
的所有值。
答案 0 :(得分:1)
Erland Sommarskog有一篇非常好的文章Dynamic Search Conditions in T‑SQL。他解释了可以使用的几种方法,并将建立动态SQL与@ lad2025建议和使用OPTION(RECOMPILE)
进行比较。
我个人在这些查询中使用OPTION(RECOMPILE)
。您使用SQL Server 2008,因此这个选项是一个不错的选择。如果您确实通过动态SQL路由,请务必阅读他的另一篇文章The Curse and Blessings of Dynamic SQL。
所以,你的程序就是这样的:
create procedure proc1
@var1 varchar(100) = null,
@var2 varchar(100) = null,
@var3 varchar(100) = null,
@var4 varchar(100) = null,
........
@var10 varchar(100) = null
as
begin
insert into #a
select * from
(
select *
from
tab1 as a
inner join tab2 as b on a.rollnumber = b.rollnumber
inner join tab3 as c on c.city = b.city
........
inner join tab10 as j on J.id = i.id
where
(a.id = @var1 OR @var1 IS NULL)
and (b.id = @var2 OR @var2 IS NULL)
and (c.id = @var3 OR @var3 IS NULL)
...........
and (J.id = @var10 OR @var10 IS NULL)
) as abc
OPTION(RECOMPILE);
if (select count(*) from #a) < 10
begin
select * from #a
end
else
begin
print 'Cannot display the records as count is more than 10'
end
end
顺便说一下,通过查看count()
并不清楚你想要实现的目标,但也许你需要的只是简单的TOP(10)
来返回最多10个第一行。如果您确实使用ORDER BY
来一致地返回结果,请务必添加TOP
子句。如果您不知道,可以使用过程的另一个参数来指示要返回的最大行数并在TOP(@ParamMaxRowCount)
中使用它。有时候返回结果集的存储过程并不常见,有时只打印一条消息。
答案 1 :(得分:0)
让我们玩Dynamic - SQL:
CREATE PROCEDURE [dbo].[my_procedure]
@var1 VARCHAR(100) = NULL,
@var2 VARCHAR(100) = NULL,
@var3 VARCHAR(100) = NULL,
@var4 VARCHAR(100) = NULL,
/* ........ */
@var10 VARCHAR(100) = NULL,
@debug INT = 0
AS
BEGIN
SET NOCOUNT ON;
DECLARE
@sql NVARCHAR(MAX),
@paramlist NVARCHAR(4000),
@nl CHAR(2) = CHAR(13) + CHAR(10);
/* Main query here */
SELECT @sql =
'SELECT *
FROM tab1 AS a
INNER JOIN tab2 AS b
ON a.rollnumber = b.rollnumber
INNER JOIN tab3 AS c
ON c.city = b.city
/* ........ and so on */
INNER JOIN tab10 AS j
ON J.id = i.id
WHERE 1 = 1 ' + @nl;
IF @var1 IS NOT NULL
SELECT @sql += ' AND a.id = @var1' + @nl;
IF @var2 IS NOT NULL
SELECT @sql += ' AND b.id = @var2' + @nl;
/* ... */
IF @var10 IS NOT NULL
SELECT @sql += ' AND j.id = @var10' + @nl;
/* If sorting needed just add it;
SELECT @sql += ORDER BY a.id;
*/
IF @debug = 1
PRINT @sql;
SELECT @paramlist =
'@var1 VARCHAR(100),
@var2 VARCHAR(100),
/* ... */
@var10 VARCHAR(100)';
/*CREATE TABLE #temp definition here */
INSERT INTO #temp(col1, col2, ...)
EXEC [dbo].[sp_executesql]
@sql,
@paramlist,
@var1,
@var2,
/* ... */
@var10;
IF @@ROWCOUNT < 10
THEN
SELECT * /* Use column names */
FROM #temp;
ELSE
PRINT 'Cannot display the records as count is more than 10';
END
如果想查看查询,则用作任何正常的存储过程+ debug:
EXEC [dbo].[my_procedure]
@var1 = 'AAA'
,@var2 = 'BBB'
,@debug = 1;
SELECT COUNT(*) FROM #temp
使用@@ROWCOUNT
; WHERE 1 = 1
,您可以先检查所有参数是否为NULL并跳过它。IF THEN ELSE IF THEN ELSE IF ... ELSE
并执行难以维护的代码的大量复制(如果使用代码行来衡量您的工作效率,那么它很有用) 答案 2 :(得分:-1)
您只需要提供正在使用的参数。
如果只需要传递Var1的值。
proc1 @Var1 = Var1Value
如果需要传递Var6的值。
Proc1 @Var6 = Var6Value
请使用此案例
where case @var1 when null then 1 else a.id end = case @var1 when null then 1 else @var1 end
希望这会对你有所帮助 感谢