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

Арт*_*нов 5 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
Run Code Online (Sandbox Code Playgroud)

Aar*_*and 16

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

USE model;
GO
CREATE SYNONYM dbo.getDays FOR master.dbo.getDays;
Run Code Online (Sandbox Code Playgroud)

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

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

  RETURN (SELECT DATEPART(DAY, DATEADD(DAY, -1, 
     DATEADD(MONTH, 1, DATEADD(DAY, 1-DAY(@date), @date)))));
Run Code Online (Sandbox Code Playgroud)

所以从顶部:

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
Run Code Online (Sandbox Code Playgroud)

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

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;
Run Code Online (Sandbox Code Playgroud)


Gor*_*off 5

虽然在 master 中创建存储过程可以使它们全局可用,但这不适用于函数。您需要使用三部分命名约定:

select <dbname>.<schema>.getDays(...)
Run Code Online (Sandbox Code Playgroud)

为什么微软会让函数不同于存储过程?

  • 亚伦,这是一个很好的答案,但为什么他们不对函数做同样的事情呢?当然,有些系统功能也受益于全球可用。 (2认同)