是否可以在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
答案 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会使函数与存储过程不同?