从函数执行存储过程

时间:2011-06-14 14:11:54

标签: sql sql-server sql-server-2005 stored-procedures user-defined-functions

我知道这已被要求死亡,我知道为什么SQL Server不允许你这样做。

但除了使用扩展存储过程之外,还有其他解决方法吗?

请不要告诉我将我的功能转换为程序......

所以我真正要问的是:有没有办法在函数中运行存储过程?

修改

点证明:有一种解决方法,但它是如此错误我不会这样做。 我要将其更改为存储过程并在其他地方执行。

5 个答案:

答案 0 :(得分:26)

编辑:我没试过这个,所以我不能保证!你已经知道你不应该这样做,所以请不要这样做。但是...

尝试查看此处:http://sqlblog.com/blogs/denis_gobo/archive/2008/05/08/6703.aspx

关键位是我试图为您的目的调整的位:

DECLARE @SQL varchar(500)

SELECT @SQL = 'osql -S' +@@servername +' -E -q "exec dbName..sprocName "'

EXEC master..xp_cmdshell @SQL

答案 1 :(得分:11)

不允许函数产生副作用,例如改变表格内容。

存储过程是。

如果一个函数称为存储过程,该函数将会产生副作用。


所以,抱歉,但不,你不能从函数调用存储过程。

答案 2 :(得分:1)

除了使用OPENQUERY和xp_cmdshell之外,另一个选项是使用SQLCLR(SQL Server' CLR Integration"功能)。 SQLCLR选项不仅比其他两种方法更安全,而且还有一个潜在的好处是能够在当前会话中调用存储过程,以便它可以访问任何会话 - 基于对象或设置,例如:

  • 临时表
  • 临时存储过程
  • CONTEXT_INFO

这可以通过使用" context connection = true;"来实现。作为ConnectionString。请记住,将强制执行对T-SQL用户定义函数的所有其他限制(即不会产生任何副作用)。

如果您使用常规连接(即不使用上下文连接),那么它将作为独立调用运行,就像使用OPENQUERY和xp_cmdshell方法时一样。

HOWEVER ,请记住,如果您将在一个影响超过1行的语句中使用调用存储过程的函数(无论您使用哪3种方法) ,然后行不能期望每行运行一次。正如@MartinSmith在对@ MatBailie的回答中提到的那样,查询优化器不保证函数执行的时间或次数。但是,如果您在SET @Variable = function();语句或SELECT * FROM function();查询中使用它,那么它应该没问题。

下面的文章(我写的)中显示了使用.NET / C#SQLCLR用户定义函数执行存储过程的示例:

Stairway to SQLCLR Level 2: Sample Stored Procedure and Function

答案 3 :(得分:0)

这是另一种可能的解决方法:

if exists (select * from master..sysservers where srvname = 'loopback')
    exec sp_dropserver 'loopback'
go
exec sp_addlinkedserver @server = N'loopback', @srvproduct = N'', @provider = N'SQLOLEDB', @datasrc = @@servername
go

create function testit()
    returns int
as
begin
    declare @res int;
    select @res=count(*) from openquery(loopback, 'exec sp_who');
    return @res
end
go

select dbo.testit()

它不像xp_cmdshell那么可怕,但也有too many implications用于实际用途。

答案 4 :(得分:0)

我已经找到解决此问题的方法。我们可以在存储过程中使用“已渲染”的sql构建功能或视图,然后可以正常执行该存储过程。

1。创建另一个存储过程

CREATE PROCEDURE [dbo].[usp_FunctionBuilder]
DECLARE @outerSql VARCHAR(MAX)
DECLARE @innerSql VARCHAR(MAX)

2。构建要在函数中执行的动态sql(示例:您可以使用循环和并集,可以读取另一个sproc,对条件sql使用if语句和参数,等等)

SET @innerSql = 'your sql'

3。将@innerSql包裹在create函数语句中,并定义您在@innerSql中使用的所有外部参数,以便可以将它们传递到生成的函数中。

SET @outerSql = 'CREATE FUNCTION [dbo].[fn_GeneratedFunction] ( @Param varchar(10))
RETURNS TABLE
AS
RETURN
' + @innerSql;


EXEC(@outerSql)

这只是伪代码,但是该解决方案解决了许多问题,例如链接服务器的限制,参数,函数中的动态sql,动态服务器/数据库/表名,循环等。

您将需要对其进行调整,(例如:在函数中更改收益)