2012-05-23 21 views
5

Czy jest możliwe utworzenie funkcji w SQL Server, której mógłbym użyć w dowolnej bazie danych na serwerze, bez dodawania prefiksu bazy danych?Czy mogę utworzyć funkcję globalną w SQL Server?

Na przykład z tej funkcji:

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 

Odpowiedz

14

Można utworzyć funkcję master (lub innej stałej bazy danych), a następnie utworzyć synonim w modelu bazy danych:

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

Spowoduje to utworzenie synonim do funkcji w jakichkolwiek nowych baz danych , ale w przypadku istniejących baz danych (lub baz danych dołączonych lub przywróconych w przyszłości) musisz skopiować tam synonim. Umożliwi to odwołanie się do obiektu z dwuczęściową nazwą w dowolnej bazie danych, przy jednoczesnym przechowywaniu tylko jednej kopii kodu.

Tak na marginesie, Twój kod może być znacznie bardziej zwięzły:

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

więc od góry:

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 

teraz, aby utworzyć synonim to w każdej bazy danych:

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" nie jest rozpoznawaną wbudowaną nazwą funkcji. –

+0

Należy utworzyć funkcję w systemie głównym, a następnie utworzyć synonim w istniejących bazach danych (nie tylko w modelu). Utworzenie go w modelu tworzy funkcję tylko w * nowych * bazach danych, które są tworzone po utworzeniu synonimu w modelu. Zawsze powinieneś zawsze ZAWSZE funkcjami referencyjnymi lub synonimami z prefiksem schematu, więc powinno to być 'dbo.getdays', a nie' getDays'. –

+0

Nie rozumiem, jak działa ten "powrót" –

3

Chociaż tworzenie procedur przechowywanych w mistrza sprawia, że ​​są dostępne na całym świecie, to nie działa dla funkcji. Konieczne jest użycie trzyczęściowej konwencji nazewnictwa:

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

Dlaczego firma Microsoft wprowadziłaby inne funkcje niż procedury składowane?

+1

Utworzenie funkcji w systemie głównym nie udostępnia jej innym bazom danych. Takie zachowanie jest prawdziwe w przypadku procedur składowanych i tylko wtedy, gdy opcja 'sp_configure' zezwala na aktualizacje' jest ustawiona na 1, lub procedura nazywa się' sp_ '. –

+0

Stworzyłem go w master, ale mój skrypt go nie widzi –

+0

Zepsułem. . . Naprawiam odpowiedź –

Powiązane problemy