Арт*_*нов 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)
虽然在 master 中创建存储过程可以使它们全局可用,但这不适用于函数。您需要使用三部分命名约定:
select <dbname>.<schema>.getDays(...)
Run Code Online (Sandbox Code Playgroud)
为什么微软会让函数不同于存储过程?