从函数执行存储过程

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从函数执行存储过程相关的知识,希望对你有一定的参考价值。

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

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

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

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

编辑:

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

答案

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

试试这里: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
另一答案

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

存储过程是。

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

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

另一答案

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

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

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

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

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

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

Stairway to SQLCLR Level 2: Sample Stored Procedure and Function

另一答案

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

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实用。

另一答案

我找到了解决这个问题的方法。我们可以在存储过程中使用“呈现的”sql构建一个Function或View,然后可以正常执行。

1.创造另一个sproc

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

2.在你的函数中构建你想要执行的动态sql(例如:你可以使用循环和联合,你可以在另一个sproc中读取,使用if语句和参数用于条件sql等)

SET @innerSql = 'your sql'

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

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


EXEC(@outerSql)

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

您需要根据需要调整它(例如:更改函数中的返回值)

以上是关于从函数执行存储过程的主要内容,如果未能解决你的问题,请参考以下文章

从 UDF 执行存储过程

存储过程在 SSMS 中执行时都返回结果,但从代码执行时只有一个返回结果

Sqlserver中存储过程,触发器,自定义函数

可以从雪花中的函数调用存储过程吗

NodeJs异步的执行过程

从Oracle存储过程Oracle 11g发送邮件