2012-05-23 32 views
5

¿Es posible crear una función en SQL Server que pueda usar en cualquier base de datos en el servidor, sin agregar el prefijo de la base de datos?¿Puedo crear crear una función global en SQL Server?

Por ejemplo, con esta función:

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 

Respuesta

14

Puede crear la función de maestro (o alguna otra base de datos permanente), y luego crear un sinónimo en la base de datos model:

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

Esto creará un sinónimo de la función en cualquier nuevos bases de datos , pero para bases de datos existentes (o bases de datos adjuntas o restauradas en el futuro) deberá copiar el sinónimo allí. Esto le permitirá hacer referencia al objeto con un nombre de dos partes en cualquier base de datos, mientras que solo tiene que almacenar una copia del código.

Como acotación al margen, el código podría ser mucho más concisa:

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

lo tanto, desde la parte superior:

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 

ahora para crear un sinónimo de esto en cada base de datos:

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; 
+0

'getDays' no es un nombre de función incorporado reconocido. –

+0

Necesita crear la función en el maestro, luego cree el sinónimo en las bases de datos existentes (no solo en el modelo). Al crearlo en el modelo, solo se crea la función en * nuevas * bases de datos que se crean después de que se haya creado el sinónimo en el modelo. Y siempre, siempre, SIEMPRE debe hacer referencia a funciones o sinónimos con el prefijo de esquema, por lo que debe ser 'dbo.getDays', no' getDays'. –

+0

No entiendo cómo funciona el 'return' –

3

Aunque la creación de procedimientos almacenados en el maestro les hace disponible a nivel mundial, esto no funciona para las funciones. Debe utilizar la convención de nomenclatura de tres partes:

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

¿Por qué Microsoft haría las funciones diferentes de los procedimientos almacenados?

+1

La creación de la función en el maestro no la hace disponible para otras bases de datos. Este comportamiento es verdadero para procedimientos almacenados, y solo cuando la opción 'sp_configure'' allow updates' está establecida en 1, o el procedimiento se llama 'sp_ '. –

+0

Lo he creado en master, pero mi script no lo ve –

+0

Me equivoqué. . . Estoy arreglando la respuesta –

Cuestiones relacionadas