2012-05-23 131 views
5

是否可以在SQL Server中创建一个可以在服务器上的任何数据库中使用的函数,而无需添加数据库前缀?我可以在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 

回答

14

您可以创建在主函数(或其他永久性的​​数据库),然后创建模型数据库的代名词:

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))))); 
从顶部

所以:

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; 

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 

我们在每个数据库中创建一个同义词为这个

+0

“getDays”不是公认的内置函数名称。 –

+0

您需要在master中创建函数,然后在现有数据库(不仅仅是模型)中创建同义词。在模型中创建它只会在模型中创建同义词后创建的* new *数据库中创建函数。并且始终应始终使用模式前缀引用函数或同义词,因此它应该是'dbo.getDays',而不是'getDays'。 –

+0

我没有低估这些“返回”的工作方式 –

3

虽然在主创建存储过程使它们全局可用,这并不为职能的工作。您需要使用三部分命名约定:

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

为什么微软的功能与存储过程不同?

+1

在主服务器中创建功能不会使其他数据库可用。对于存储过程,这种行为是正确的,并且只有当'sp_configure'选项'allow updates'设置为1或过程名为'sp_ '时。 –

+0

我创建它在主,但我的脚本没有看到它 –

+0

我搞砸了。 。 。我正在修复答案 –

相关问题