从函数执行存储过程
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,动态服务器/数据库/表名,循环等。
您需要根据需要调整它(例如:更改函数中的返回值)
以上是关于从函数执行存储过程的主要内容,如果未能解决你的问题,请参考以下文章