2010-04-02 127 views
24

我已经看过有关此问题的Stack Overflow的其他问题,但他们都没有清楚地回答这个问题。使用SQL来过滤存储过程的结果

我们有一个名为sp_who2的系统存储过程,它返回服务器上所有正在运行的进程的信息结果集。我想过滤存储过程返回的数据;从概念上讲,我可能会这样做:

SELECT * FROM sp_who2 
WHERE login='bmccormack' 

该方法虽然不起作用。实现查询存储过程返回数据的目标的最佳做法是什么,最好不必查看原始存储过程的代码并对其进行修改。

回答

27

没有好的方法来做到这一点。这是存储过程的限制。您的选项有:

  1. 将程序切换到User Defined Function。在今天的世界上,人们正在制定应该是功能的存储过程。这是一个教育问题。你的情况就是一个很好的例子。如果你的程序是不是一个UDF,你可能只是做到以下几点,完全按照自己的直觉地认为你应该能够:

    SELECT * FROM udf_who2() 
    WHERE login='bmccormack' 
    
  2. 如果你真的不能碰你的程序,并必须有这个在SQL中完成,那么你将不得不时髦。使另一个存储过程来包装您的原始过程。在新过程中调用现有过程并将值放入临时表中,然后使用所需过滤器对该表运行查询,并将结果返回给外部世界。

从SQL Server 2005开始,用户定义的函数就是封装数据检索的方式。存储过程以及视图是在特定情况下使用的专业工具。他们在正确的时间都非常方便,但不是第一选择。有些人可能会认为上面的例子(A)获得了该函数的所有结果,然后(B)对该结果集进行过滤,就像子查询一样。 情况并非如此。 SQL Server 2005+优化该查询;如果在login上有索引,则在查询执行计划中看不到表扫描;非常有效。

编辑:我应该补充一点,UDF的内脏类似于SP的内脏。如果它与您想要避免的SP的逻辑混淆,您仍然可以将其更改为函数。有几次,我采取了大量可怕的程序代码,我不想理解,并成功将其转换为函数。唯一的问题将是如果程序修改除了返回结果之外; UDF不能修改数据库中的数据。

+0

需要提醒的是有潜在的内联表值函数和多语句表值函数之间有很大的区别。内联TVF可以像视图一样进行优化,并且它们对(参数化)视图的行为要比对函数的行为要密切得多。 – 2010-04-03 11:10:11

+0

@Case Roux非常好的一点!如果它是一个多语句函数,选项1将增加简单性,但可能不会提高性能。对于大量的行,可能是一条狗。如果性能很重要,选项2可能会更快。一如既往地依赖于这种情况。 – 2010-04-03 13:41:51

+0

如果存储过程使用临时表,这可能不起作用。 由于用户定义的函数不能创建临时表。 – yucer 2014-11-10 10:21:25

2

将数据放在Table变量或Temp表中并对其进行过滤。

+3

如何,请加一个例子,由于 – Mathematics 2015-09-14 09:48:50

9

你可以做一个OPENROWSET(),但也有一些安全/性能问题。

SELECT * 
FROM OPENROWSET ('SQLOLEDB', 'Server=(local);TRUSTED_CONNECTION=YES;', 'exec mystoredproc') 

传统上,将其添加到临时变量/表将工作。

7

过滤临时表是可能的方法。

-- Create tmp table from sp_who results 
CREATE TABLE #TmpWho 
(spid INT, ecid INT, status VARCHAR(150), loginame VARCHAR(150), 
hostname VARCHAR(150), blk INT, dbname VARCHAR(150), cmd VARCHAR(150), request_id INT) 
INSERT INTO #TmpWho 
EXEC sp_who 

-- filter temp table where spid is 52 
SELECT * FROM #TmpWho 
WHERE spid = 52 

DROP TABLE #TmpWho