Globale Stored Procedure im SQL Server

Um eine Stored Procedure im SQL Server global (d.h. über mehrere Datenbanken hinweg) verfügbar zu machen, gibt es den nur wenig (bzw. offiziell gar nicht) dokumentierten Befehl sp_ms_marksystemobject. Damit es funktioniert muss der Name der Stored Procedure mit “sp_” beginnen und in der master-Datenbank gespeichert sein! Es gibt keine Fehlermeldung, falls dies nicht so wäre…

Folgende Tabelle soll den Unterschied verdeutlichen. Die Aufgerufene Stored Procedure gibt (wie in dem Beispiel unten) lediglich den aktuellen Datenbanknamen zurück.

Stored ProcedureAufruf aus AdventureWorks-DBDB_NAME()
in master-Datenbank, aber nicht als System Object markiert
EXEC master.dbo.StoredProcedure
master
EXEC dbo.StoredProcedure
Fehler
in master-Datenbank und als System Object markiert
EXEC master.dbo.StoredProcedure
master
EXEC dbo.StoredProcedure
AdventureWorks

Der Aufruf einer als System-Objekt markierten Stored Procedure erfolgt also, als ob diese in der lokalen Datenbank vorhanden wäre.

Achtung: dieser Befehl ist undokumentiert und kann in einer der nächsten Versionen wegfallen… Die Verwendung ist auf live-Systemen daher nicht zu empfehlen.

Beim Entwickeln stört das allerdings nur wenig - und wenn man sich Hilfsfunktionen schreibt, die man in jeder Datenbank mal gebrauchen kann, dann steht der Verwendung dieses Befehls auch nichts im Wege (bis er wegfällt *g*).

Immer in einer lokalen Datenbank zu arbeiten bringt den Vorteil mit sich, dass man auch lokale Objekte ansprechen kann, ohne beim Entwickeln wissen zu müssen, in welcher Datenbank dies geschehen soll. Das erleichtert z.B. den Zugriff auf die sys-Views für unterschiedliche Datenbanken. Allerdings kann das auch bedeuten, dass die entsprechende Tabelle nicht vorhanden ist oder über andere Spaltennamen verfügt. Das sollte man beim Erstellen der Prozedur im Hinterkopf behalten.

Zum Testen:

1
2
3
4
5
6
7
8
9
USE master
GO
CREATE PROCEDURE sp_testGlobal
AS BEGIN
SELECT DB_NAME() AS CurrentDB
END
GO
EXEC sp_ms_marksystemobject 'sp_testGlobal'

Diese Stored Procedure gibt den aktuellen Datenbanknamen zurück und kann nun aus jeder anderen Datenbank aufgerufen werden..

Will man übrigens wirklich eine lokale Tabelle, View, Gespeicherte Prozedur oder Funktion aufrufen, dann muss man diese eventuell (zumindest kurzfristig) auch in der master-Tabelle anlegen, da es sonst Fehler beim Anlegen/Ändern der globalen gespeicherten Prozedur geben könnte. Auch IntelliSense ist an dieser Stelle ohne entsprechende Objekte nicht möglich. Etwas einfacher und eleganter geht es mit einem Alias, der in der master-Tabelle eingerichtet wird (aber meistens klappts ja auch einfach so).

Das Ganze funktioniert (trotz mehrfacher, gegenteiliger Ankündigung) immer noch - auch noch im SQL Server 2008. Dort aber leider ohne IntelliSense-Unterstützung.