Can I create create a global function in SQL Serve

2020-03-19 03:50发布

问题:

Is it possible to create a function in SQL Server which I could use in any database on the server, without adding the database prefix?

For example, with this function:

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

回答1:

You can create the function in master (or some other permanent database), and then create a synonym in the model database:

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

This will create a synonym to the function in any new databases, but for existing databases (or databases attached or restored in the future) you'll need to copy the synonym there. This will allow you to reference the object with a two-part name in any database, while only having to store one copy of the code.

As an aside, your code could be much more concise:

  RETURN (SELECT DATEPART(DAY, DATEADD(DAY, -1, 
     DATEADD(MONTH, 1, DATEADD(DAY, 1-DAY(@date), @date)))));

So from the top:

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

Now to create a synonym for this in each database:

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;


回答2:

Although creating stored procedures in master makes them globally available, this does not work for functions. You need to use the three-part naming convention:

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

Why would Microsoft make functions different from stored procedures?