我可以在SQL Server中创建创建全局函数吗?

时间:2012-05-23 21:13:20

标签: sql sql-server-2008

是否可以在SQL Server中创建一个可以在服务器上的任何数据库中使用的函数,而无需添加数据库前缀?

例如,使用此功能:

CREATE FUNCTION getDays (@date date)
RETURNS INT
AS
BEGIN

RETURN CASE WHEN MONTH(@date) IN (1, 3, 5, 7, 8, 10, 12) THEN 31
            WHEN MONTH(@date) IN (4, 6, 9, 11) THEN 30
            ELSE CASE WHEN (YEAR(@date) % 4    = 0 AND
                            YEAR(@date) % 100 != 0) OR
                           (YEAR(@date) % 400  = 0)
                      THEN 29
                      ELSE 28
                 END
       END

END

2 个答案:

答案 0 :(得分:16)

您可以在master(或其他一些永久数据库)中创建该函数,然后在model数据库中创建一个同义词:

USE model;
GO
CREATE SYNONYM dbo.getDays FOR master.dbo.getDays;

这将在任何 new 数据库中创建该函数的同义词,但对于现有数据库(或将来附加或恢复的数据库),您需要在那里复制同义词。这将允许您在任何数据库中引用具有两部分名称的对象,而只需存储一个代码副本。

顺便说一句,您的代码可以更加简洁:

  RETURN (SELECT DATEPART(DAY, DATEADD(DAY, -1, 
     DATEADD(MONTH, 1, DATEADD(DAY, 1-DAY(@date), @date)))));

所以从顶部开始:

USE [master];
GO
DROP FUNCTION dbo.getDays;
GO
CREATE FUNCTION dbo.getDays
(
    @date DATE
)
RETURNS INT
AS
BEGIN
    RETURN (SELECT DATEPART(DAY, DATEADD(DAY, -1, 
         DATEADD(MONTH, 1, DATEADD(DAY, 1-DAY(@date), @date)))));
END
GO

现在在每个数据库中为此创建一个同义词:

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += CHAR(13) + CHAR(10) 
+ 'USE ' + QUOTENAME(name) + ';

IF OBJECT_ID(''dbo.getDays'', ''FN'') IS NOT NULL
  DROP FUNCTION dbo.getDays;

IF OBJECT_ID(''dbo.getDays'', ''SN'') IS NOT NULL
  DROP SYNONYM dbo.getDays

CREATE SYNONYM dbo.getDays FOR master.dbo.getDays;'
 FROM sys.databases WHERE name <> 'master';

PRINT @sql;

EXEC sp_executesql @sql;

答案 1 :(得分:3)

尽管在master中创建存储过程使它们全局可用,但这对函数不起作用。您需要使用三部分命名约定:

select <dbname>.<schema>.getDays(...)

为什么Microsoft会使函数与存储过程不同?