Ich habe eine Funktion, die in mehr als einem Dutzend Datenbanken verwendet wird. Ich möchte, dass auf diese Funktion in allen Datenbanken zugegriffen werden kann, indem sie nur einmal geschrieben wird. Daher möchte ich die Funktion in die Master-Datenbank schreiben, damit auf meine Funktion problemlos zugegriffen werden kann.
Gibt es ein Problem beim Schreiben der benutzerdefinierten Funktion in der Master-Datenbank?
Beim Surfen im Internet wurde empfohlen, die Funktion in eine Systemfunktion umzuwandeln. (Verwenden von "EXEC sp_ms_marksystemobject 'fn_db_name'").
Muss die in master db erstellte Funktion in eine Systemfunktion konvertiert werden? Wenn ja warum?
sql-server
sql-server-2008-r2
functions
IT-Forscher
quelle
quelle
Antworten:
Ich stimme Jonathan zu - solange die Funktion keine lokalen Daten basierend auf dem aufrufenden Datenbankkontext zurückgeben soll, stellen Sie die Funktion in eine Dienstprogrammdatenbank (hier füge ich auch Dinge wie Zahlen und Kalendertabellen, Aufteilungsfunktionen usw. Ein ):
Erstellen Sie jetzt in jeder Datenbank, die auf die Funktion zugreifen muss, einfach ein Synonym:
Auf diese Weise kann jede Datenbank weiterhin mit einem einfachen zweiteiligen Namen auf die Funktion verweisen - und sie müssen nicht wissen oder sich darum kümmern, wo sie tatsächlich vorhanden ist. Und Sie müssen nur eine einzige Kopie der Funktion pflegen.
(Tatsächlich können Sie das Synonym in die
model
Datenbank einfügen, sodass es automatisch in neuen Datenbanken erstellt wird.)Der Grund, warum ich Benutzerobjekte
master
nicht gerne einfüge - es sei denn, sie müssen wirklich global verfügbar und kontextbezogen für die aufrufende Datenbank sein, wie Ihre eigene angepasste Version vonsp_spaceused
odersp_helpindex
-, ist, dass Benutzer nicht nach Benutzerobjekten suchenmaster
und weniger dort auffindbar. Sie erschweren auch die Migration Ihrer Benutzerdatenbanken an einen anderen Ort, da Sie sich auch an die von Ihnen eingegebenen Benutzerdaten erinnern müssenmaster
. Wenn Sie absolut nicht in dermsdb
Lage sind , eine Dienstprogrammdatenbank dafür zu erstellen oder zu verwenden, ist dies meiner Meinung nach eine praktischere Wahl für einen zentralen Standort.quelle
Obwohl ich @Jonathan und @Aaron zustimme, dass Sie eine "Dienstprogramm" -Datenbank verwenden sollten (ich nenne sogar meine
Utility
), und ich Aaron bei der Verwendung von Synonymen zustimme, möchte ich auf die Einschränkung aufmerksam machen, die Aaron so erwähnt hat wichtig:Das heißt, wenn Sie noch den „aktuelle Datenbank“ Kontext müssen (im Gegensatz zu dem Code Gegensatz in der Datenbank ausgeführt wird, wo es tatsächlich existiert, ob es sein
master
oderUtility
), dann etwas mit , abermaster
nicht funktionieren.Wenn Sie also die Funktion benötigen, um im Kontext der Datenbank ausgeführt zu werden, von der aus sie aufgerufen wird , funktioniert der Plan zur Verwendung einer Funktion ohnehin nicht, da Code in der
master
Datenbank vorhanden ist, der im aktuellen Datenbankkontext ausgeführt werden kann undmaster
nur funktioniert für gespeicherte Prozeduren, auch wenn Sie die undokumentiertesp_ms_marksystemobject
gespeicherte Systemprozedur verwenden, um Ihre Funktion als Systemobjekt zu markieren. Wenn Sie dem Namen der Funktion ein Präfix voranstellenfn_
oder sogarsp_
nicht zulassen, dass er außerhalb des Masters gefunden wird, ohne den Objektnamen vollständig zu qualifizieren. Selbst wenn Sie den Namen vollständig qualifizierenmaster
, wird er auch nach dem Markieren als Systemobjekt nur im Kontext der Datenbank ausgeführt.Sie haben also drei Möglichkeiten:
Utility
Datenbank für das Objekt zu verwenden, und verwenden Sie Synonyme in den Datenbanken, die die Funktion verwenden müssen, um auf dieUtility
Datenbank zu verweisen .Wenn Sie den aktuellen DB-Kontext benötigen:
sp_
und führen Sie diesp_ms_marksystemobject
gespeicherte Systemprozedur darauf aus, um sie als gespeicherte Systemprozedur zu markieren (andernfalls wird der aktuelle DB-Kontext für Abfragen nicht wiedergegeben, obwohl dies für einige erstellte Prozeduren der Fall ist -in funktioniert wieDB_NAME()
). Ich bin kein großer Fan dieses Ansatzes, aber es funktioniert.Verwenden Sie SQLCLR, um eine Funktion zu erstellen, die in die
Utility
Datenbank eingefügt werden kann und an die der aktuelle Datenbankname (oder ein beliebiger Datenbankname) übergeben wird, um das dynamische SQL zu erstellen, das die übermittelte Abfrage sein wird. In der folgenden Antwort habe ich ein Beispiel dafür mit SQLCLR veröffentlicht, auch auf DBA.StackExchange:Zentrale gespeicherte Prozedur zur Ausführung im aufrufenden Datenbankkontext
Sie können bei diesem Ansatz auch Synonyme verwenden. Anschließend rufen Sie die Funktion beim Übergeben auf
DB_NAME()
, um den aktuellen Datenbanknamen automatisch einzugeben.quelle