9

是否可以在 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
4

2 回答 2

19

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

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

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

顺便说一句,您的代码可能会更简洁:

  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;
于 2012-05-23T21:21:24.790 回答
5

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

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

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

于 2012-05-23T21:18:06.493 回答