我可以在脚本或存储过程中创建一次性使用函数吗?

时间:2009-06-11 14:30:33

标签: sql sql-server sql-server-2005 tsql scripting

在SQL Server 2005中,是否存在在SQL脚本或存储过程中声明的一次性使用或本地函数的概念?我想在我正在编写的脚本中抽象出一些复杂性,但它需要能够声明一个函数。

好奇。

6 个答案:

答案 0 :(得分:75)

您可以创建临时存储过程,例如:

create procedure #mytemp as
begin
   select getdate() into #mytemptable;
end

在SQL脚本中,但不是函数。你可以让proc将结果存储在临时表中,然后在脚本中使用该信息..

答案 1 :(得分:62)

您可以在脚本开头附近调用CREATE Function,在结尾附近调用DROP Function

答案 2 :(得分:21)

Common Table Expressions让您定义基本上只在select,insert,update和delete语句范围内的视图。根据您的需要,它们非常有用。

答案 3 :(得分:10)

我知道我可能因为建议动态SQL而受到批评,但有时它是一个很好的解决方案。在考虑之前,请确保您了解安全隐患。

DECLARE @add_a_b_func nvarchar(4000) = N'SELECT @c = @a + @b;';
DECLARE @add_a_b_parm nvarchar(500) = N'@a int, @b int, @c int OUTPUT';

DECLARE @result int;
EXEC sp_executesql @add_a_b_func, @add_a_b_parm, 2, 3, @c = @result OUTPUT;
PRINT CONVERT(varchar, @result); -- prints '5'

答案 4 :(得分:3)

在脚本中,您有更多选择,更好地理解分解。查看SQLCMD模式(查询菜单 - > SQLCMD模式),特别是:setvar和:r命令。

在存储过程中,您的选项非常有限。您无法直接使用过程主体创建定义函数。你可以做的最好的事情是动态SQL:

create proc DoStuff
as begin

  declare @sql nvarchar(max)

  /*
  define function here, within a string
  note the underscore prefix, a good convention for user-defined temporary objects
  */
  set @sql = '
    create function dbo._object_name_twopart (@object_id int)
    returns nvarchar(517) as
    begin
      return 
        quotename(object_schema_name(@object_id))+N''.''+
        quotename(object_name(@object_id))
    end
  '

  /*
  create the function by executing the string, with a conditional object drop upfront
  */
  if object_id('dbo._object_name_twopart') is not null drop function _object_name_twopart
  exec (@sql)

  /*
  use the function in a query
  */
  select object_id, dbo._object_name_twopart(object_id) 
  from sys.objects
  where type = 'U'

  /*
  clean up
  */
  drop function _object_name_twopart

end
go

如果存在这样的事情,这将近似于全局临时函数。它仍然可供其他用户看到。您可以附加连接的@@ SPID来唯一化名称,但这将要求其余的过程也使用动态SQL。

答案 5 :(得分:3)

以下是我过去用来完成MS SQL中Scalar UDF的需求:

IF OBJECT_ID('tempdb..##fn_Divide') IS NOT NULL DROP PROCEDURE ##fn_Divide
GO
CREATE PROCEDURE ##fn_Divide (@Numerator Real, @Denominator Real) AS
BEGIN
    SELECT Division =
        CASE WHEN @Denominator != 0 AND @Denominator is NOT NULL AND  @Numerator != 0 AND @Numerator is NOT NULL THEN
        @Numerator / @Denominator
        ELSE
            0
        END
    RETURN
END
GO

Exec ##fn_Divide 6,4

这种使用PROCEDURE全局变量的方法使您不仅可以在脚本中使用该函数,还可以在动态SQL需求中使用该函数。