我知道这已被要求死亡,我知道为什么SQL Server不允许你这样做。
但除了使用扩展存储过程之外,还有其他解决方法吗?
请不要告诉我将我的功能转换为程序......
所以我真正要问的是:有没有办法在函数中运行存储过程?
修改
点证明:有一种解决方法,但它是如此错误我不会这样做。 我要将其更改为存储过程并在其他地方执行。
答案 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 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,动态服务器/数据库/表名,循环等。
您将需要对其进行调整,(例如:在函数中更改收益)