2009-07-30 11 views
1

In einer einzigen SQL Server-Instanz laufen, ich habe die folgenden Datenbanken:Wie eine gespeicherte Prozedur in mehreren Datenbanken

  • Hauptsitz
  • Branch001
  • Branch002
  • Branch003

...

  • Niederlassung nnn

in jedem Zweig DB ist ein Verfahren usp_ComputeDailySales genannt, die eine gewisse Berechnung tut und tägliche Verkaufszahlen der Headquarters DB schreibt. Wie schreibe ich eine einzelne gespeicherte Prozedur in der Stammdatenbank, um usp_ComputeDailySales in allen Branch DBs auszuführen?

Ich könnte etwas wie den Code unten schreiben, aber ich denke, das ist nicht der Weg zu gehen.

USE Branch001 
EXEC usp_ComputeDailySales 

USE Branch002 
EXEC usp_ComputeDailySales 

... 

Ich wollte einen Weg, um die Prozedur für alle Branch DBs gleichzeitig auszuführen.

Antwort

2

Dies ist kein dynamisches SQL, sondern beruht auf einer verzögerten Namensauflösung.

EXECUTE finden @module_name_var Parameter

DECLARE @sql varchar(300) 
SELECT 
    [name] + '..usp_ComputeDailySales' AS Cmd 
INTO #List 
FROM 
    sys.databases d WHERE d.[name] LIKE 'branch%' 
    OR --Thanks Mitch 
    d.[name] = 'Headquarters' 

WHILE EXISTS (SELECT * FROM #List) 
BEGIN 
    SELECT TOP 1 @SQL = Cmd FROM #List 
    EXEC @SQL 
    DELETE #List WHERE Cmd = @SQL 
END 

bearbeiten, nachdem Kommentar des KM

Ja, ein Unterschied ist, aber ich werde klären:

EXEC (@SQL) bedeutet, konnte @SQL be 'SELECT * FROM foo' ODER 'DELETE User WHERE 1=1';.)

EXEC @SQL bedeutet @SQL ist ein Objektname. Also soll ich @Obj verwendet habe

So können Sie dies tun:

DECLARE @Obj varchar(200) 
SELECT @Obj = 'dbo.uspCustomHook' 
IF OBJECT_ID(@Obj) IS NOT NULL 
    EXEC @Obj @p1 = 1, @p2 = 'bob', ... 

Es latenten Fehler Namensauflösung vermeidet. Wenn der Batch/Proc kompiliert wird, gibt es keinen Fehler, wenn dbo.uspCustomHook nicht existiert.

Ich habe die Technik seit SQL 2000 nicht verwendet, und ich weiß nicht, ob SQL 2005 (Neukompilierung auf Anweisungsebene) schlau genug ist, um herauszufinden, ob @Obj ausgeführt werden sollte, weil es nicht existiert nicht versuchen, die EXEC-Anweisung zu kompilieren ...

Es ist auch nützlich für cross-Datenbank, gleiche Instanz Abfragen. Sie können prd-prod, dev-dev usw. konfigurieren, ohne auf verknüpfte Server oder fest codierte Datenbanken angewiesen zu sein.

+1

..OR d. [Name] = 'Hauptquartier' ... –

+0

+ 1. schlag mich dazu! ;) –

+0

Letzte Woche habe ich tatsächlich an etwas gearbeitet, das fast genau so ist. Ich habe die dynamische SQL: _EXEC (@SQL) _, gibt es einen Vorteil oder einen Unterschied mit _EXEC @ SQL? –

0

Gerade genannt nutzen könnten sie mit ihren voll qualifizierten Namen ansprechen wie:

<Database Name>.<owner>.<table> 

und die Werte ersetzen.

Beispiel: CustomerDatabase.dbo.Users

Und in Ihrem Fall wird es wie folgt aussehen:

exec Branch001.dbo.usp_ComputeDailySales 
exec Branch002.dbo.usp_ComputeDailySales 
exec Branch003.dbo.usp_ComputeDailySales 

Dies setzt voraus, eine Benutzerberechtigungen haben für alle diese Datenbanken.

0

Sie können dies relativ einfach mit sp_msForEachDB tun. Die erste Probe wird hier das proc auf jeder Datenbank ausführen, die LIKE ‚Niederlassung%‘ bezeichnet wird:

EXECUTE sp_msForEachDB ' 
IF ''?'' like ''Branch%'' 
BEGIN 
    USE ? 
    EXECUTE usp_ComputeDailySales 
END 
' 

Und diese läuft es auf jeder Datenbank (unabhängig von Namen), die eine gespeicherte Prozedur mit diesem Namen:

Herumstoßen und mit diesen aufbrauchen - sie funktionieren, aber sie brauchen ein bisschen gewöhnungsbedürftig.

Addenda: Während dies eine "undokumentierte Funktion" ist, ist es eine seit SQL Server 7.0 und möglicherweise früher. Es gibt eine beliebige Anzahl von Artikeln und Samples, die es benutzen, und wahrscheinlich eine beliebige Anzahl von Enterprise-Systemen, die darauf basieren, von denen ich einige gebaut habe. Ich habe wirklich nie irgendwelche Probleme damit gehabt (einmal habe ich das bekommen? Und das Doppelte ist richtig, das ist.)

Verwandte Themen