2016-04-27 6 views
0

Also, eine kleine Hintergrundgeschichte zu diesem:Wie setze ich einen Datenbanknamen, der eine bestimmte Tabelle enthält, auf Variable?

Ich habe eine lange Abfrage, die ich häufig für meine Aufträge verwenden, die die sp_MSForEachDB gespeicherten Proc verwendet. Die Abfrage erstellt eine temporäre Tabelle und durchsucht anschließend sys.tables. Wenn eine Datenbank eine Tabelle mit dem Namen T_Study aufweist, wird die Abfrage ausgeführt und diese Ergebnisse in die temporäre Tabelle übernommen.

Was ich jetzt versuche, ist in einer anderen Tabelle aus einer anderen Datenbank beizutreten, und diese Datenbank ist von einem anderen Typ. Diese Datenbanken unterscheiden sich alle durch die Existenz T_BatchStores. Alle Datenbanken, die eine T_BatchStores Tabelle haben, haben auch eine Tabelle dbo.T_TSyntax, und das ist die Tabelle, an der ich mich anschließen muss.

Im Wesentlichen versuche ich eine universelle Abfrage zu erstellen, die ich auf jedem Server mit dieser Software ausführen kann, und ich habe diese paar universellen Tabellen, aber die Namen der Datenbanken selbst variieren.

Also, was ich tun möchte, ist, meine Abfrage, die meine temporäre Tabelle auffüllt, fügen Sie folgende:

JOIN '[email protected]+'.dbo.T_TSyntax und meine dann ON-Klausel, usw. Beachten Sie, dass in diesem Fall kommt in meinem Anfang und Ende Klauseln und dass sp_MSforEachDb wird auf diesem ausgeführt werden.

Ich möchte nur ein zufällig ausgewählter Name der Datenbank in ihrer SQL-Instanz, die eine T_BatchStores Tabelle enthält - es ist egal, was der Name ist - ich möchte nur nicht die Abfrage jedes Mal ändern, wenn ich laufe es.

Wie kann ich meine DECLARE @MEDDB und SET/SELECT @MEDDB verwenden, um mit diesen Anforderungen zu arbeiten?

Auch in einigen lesen, ich lese, dass ich SYSNAME als Datentyp verwenden sollte, aber ich weiß auch NVARCHAR würde funktionieren - aber ich würde nur gerne einen Tipp, auf dem wäre ideal.

Ich habe versucht, die folgenden:

DECLARE @MEDDB SYSNAME 

SET @MEDDB = (SELECT TOP 1 name FROM sys.databases WHERE EXISTS (SELECT name FROM sys.tables WHERE name = '''T_BATCHSTORES''')) 

SELECT @MEDDB 

Aber diese gibt 1 Zeile mit einem NULL Wert. Ich bin sehr ein Anfänger zu SQL, also würde jede Hilfe sehr geschätzt werden!

Hinweis: Ich verwende derzeit nur Microsoft SQL Server 2008 und 2012.

Danke!

Okay, nachdem wir die Abfrage stark modifiziert haben, so dass die Namen nicht wirklich identisch sind mit unserer tatsächlichen Tabellenstruktur, hier ist eine abgespeckte Version der Abfrage, die ich verwende, damit Sie sehen, was ich sind dabei für:

/* Add or change variables as needed and comment back in WHERE statements in Insert section as needed. 
You do not need to delete any variables in this section, even if you do not need them. 
Simply comment in or out relevant data in the WHERE clause in Section 4. */ 


/* Section 1: Declaring variables. */ 

DECLARE @STUID NVARCHAR (65) 
DECLARE @IMUID NVARCHAR (200) 
DECLARE @ACCN NVARCHAR (100) 
DECLARE @MEDDB NVARCHAR (255) 

/* Section 2: Assigning values to variables such as an Image file's UID. */ 

SET @STUID = 'enterSTUID' 
SET @IMUID = 'enterIMUIDhere' 
SET @ACCN = 'enterACCNhere' 
SET @MEDDB = (SELECT TOP 1 name FROM sys.databases WHERE [name] LIKE '%med%' 
AND [name] NOT LIKE '%audit%') 


/* Section 3: Creating our temporary table to dump our results. */ 

IF OBJECT_ID('tempdb.dbo.#tempBatchResultsD6') IS NULL 

BEGIN 

CREATE TABLE #tempBatchResultsD6 

(
Database_Name VARCHAR (200), 
THING1 VARCHAR(100) NOT NULL, 
THING2 VARCHAR(200) NOT NULL, 
THING3 DATETIME NOT NULL, 
TSyntaxUID VARCHAR (66) NOT NULL, 
TSyntaxDesc VARCHAR (128) NOT NULL 
) 
END 

TRUNCATE TABLE #tempBatchResultsD6 


/* Section 4: Query that will be used to populate the contents of the temporary table created above. 
Utilizing the stored procedure "sp_MSForEachDb," this will search every database on the SQL instance. 
Here, we are limiting our results to only searching specific databases by only returning results from databases that have a "T_Studies" table. */ 

DECLARE @Command NVARCHAR(MAX) 

SET @Command = N'USE [?]; 
IF EXISTS (SELECT * FROM sys.tables WHERE [name] = ''T_Studies'') 
BEGIN 

INSERT #tempBatchResultsD6 

SELECT 

DB_Name() as Database_Name, 
THING1, 
THING2, 
THING3, 
TS.TSyntaxUID, 
TS.TSyntaxDesc 

FROM T_Studies ST WITH (nolock) 
    JOIN T_Patients PT WITH (nolock) ON ST.ST_PT_FOLDERID = PT.PT_FOLDERID 
    JOIN T_Series SE WITH (nolock) ON ST.ST_FOLDERID = SE.SE_ST_FOLDERID 
    JOIN T_Images IM WITH (nolock) ON SE.SE_FOLDERID = IM.IM_SE_FOLDERID 
    JOIN '[email protected]+'.dbo.T_TSyntaxes TS WITH (nolock) on IM.IM_TSyntaxID = TS.TSyntaxUID 

WHERE ST.STUID = '''[email protected]+''' 
--WHERE IM.IM_UID = '''[email protected]+''' 
--WHERE ST.ST_ACCNNO = '''[email protected]+''' 


END' 

EXEC sp_MSForEachDb @Command 


/* Section 5: Querying our temporary table to get our results. */ 

SELECT 

Database_Name, 
THING1, 
THING2, 
THING3, 
TSyntaxUID, 
TSyntaxDesc 

FROM #tempBatchResultsD6 

ORDER BY Database_Name 

so wie Sie sehen können, ist dies eine massive temporäre Tabelle, die aus allen Datenbanken ziehen wird, die eine T_Studies Tabelle in ihnen hat. Es ist riesig in seiner tatsächlichen Form, aber das ist deutlich reduziert.

Das Problem kommt in Abschnitt 2, wo ich @MEDDB verwende, um einen zufälligen Datenbanknamen zu wählen, wenn der Name das Wort "Med" enthält, aber nicht das Wort "Audit". Dies ist problematisch, da es eine konsistente Namensgebung auf allen Sites voraussetzt - und obwohl diese Namen vorgeschlagen werden, sind sie niemals eine Garantie.

Um Konsistenz zu gewährleisten, versuche ich, die Variable @MEDDB mit dem Namen der Datenbank auf ihrem System zu füllen, die eine T_BatchStores-Tabelle statt der WHERE [Name] wie Teil enthält.

Jeder Rat mit dieser neuen Info würde sehr geschätzt werden!

+0

Sie können eine Variable nicht als Namen der Quellentabelle verwenden. Aber Sie können 'IF-ELSE' Logik verwenden oder Sie können dynamisches SQL verwenden ... – Shnugo

+0

Können Sie klären? Ich kann SELECT @MEDDB = (SELECT-Name FROM sys.databases WHERE [Name] wie '% med%' UND [Name] nicht wie '% Audit%'), um meine Variable als eine Alternative, und dann Der Join funktioniert: JOIN'[email protected]+'.dbo.T_TSyntax on ... Ich kann nicht herausfinden, warum das so anders ist. –

Antwort

0

Ich bin mir nicht sicher, ob ich Ihre Frage vollständig verstehe. Aber wenn Sie alle Datenbanken durchlaufen möchten, können Sie etwas wie den folgenden Code verwenden. "SELECT XXX" wäre dann Ihre Abfrage, indem Sie "use '+ @DB_Name +';" Sie wechseln zur gewünschten Datenbank, um Ihre Abfrage auszuführen.

DECLARE @DB_Name varchar(100) 
DECLARE @Command nvarchar(max) 

DECLARE database_cursor CURSOR FOR 
SELECT name 
FROM MASTER.sys.sysdatabases 

OPEN database_cursor 

FETCH NEXT FROM database_cursor INTO @DB_Name 

WHILE @@FETCH_STATUS = 0 
BEGIN 


    set @Command = 
    ' 
     use ' + @DB_Name + '; 


     SELECT XXX 
    ' 


    EXEC sp_executesql @Command 

    FETCH NEXT FROM database_cursor INTO @DB_Name 

END 

CLOSE database_cursor 
DEALLOCATE database_cursor 
+0

Ich merke, dass diese Abfrage irrsinnig verwirrend ist, bis ich die ganze Sache teilen kann. Da die proprietäre Software und die Tabellennamen universell sind, muss ich alle Tabellennamen vor der Veröffentlichung ändern, damit ich keine Probleme bekomme. Bare mit mir, und ich werde die ganze Sache posten, damit es klarer ist, was ich vorhabe. Danke für die Antwort! –

+0

Okay, ich habe den ursprünglichen Beitrag so modifiziert, dass er eine modifizierte Version von dem enthält, wofür ich vorgehe. Hoffentlich wird das helfen. –

0
DECLARE @MEDDB NVARCHAR(500) 
SET @MEDDB = 'SELECT TOP 1 name FROM sys.databases WHERE EXISTS (SELECT name FROM sys.tables WHERE name = ''T_BATCHSTORES'')' 
EXEC (@MEDDB) 

Dieses dynamische SQL. Natürlich bekomme ich auch keine Ergebnisse, aber ich bin nicht in Ihrer Datenbank. Dennoch können Sie so ‚dynamisch‘, und verwenden Sie eine Variable sein, die Dinge zu ändern: Sie bauen sie in die dynamische Methode

DECLARE @MEDDB NVARCHAR(500) 
DECLARE @MEDDB2 NVARCHAR(100) = 'T_BATCHSTORES' 
SET @MEDDB = 'SELECT TOP 1 name FROM sys.databases WHERE EXISTS (SELECT name FROM sys.tables WHERE name = ''' + @MEDDB2 + ''')' 
EXEC (@MEDDB) 

Meine Empfehlung ist, dass Sie einfache Abfragen ausführen, die zeigen, was Sie wollen, und dann.

Zum Beispiel, ich bin jetzt in Adventureworks, so kann ich tun:

SELECT * FROM sys.databases 

Dies gibt mir eine Liste aller Datenbanken, die hier zur Verfügung stehen.

Vielleicht erweitere ich die

SELECT * FROM sys.databases WHERE name = 'AdventureWorks' 

Das ist mir nur eine Zeile der Ergebnisse. Also, wenn das ist, was ich will, ich baue es in den dynamischen Teil:

DECLARE @MEDDB NVARCHAR(500) 
DECLARE @MEDDB2 NVARCHAR(100) = 'AdventureWorks' 
SET @MEDDB = 'SELECT * FROM sys.databases WHERE name =''' + @MEDDB2 + '''' 
EXEC (@MEDDB) 

Es ist einfach alles hängt, was Sie suchen. Ich finde immer zuerst die Daten, die ich will, und finde dann heraus, wie ich meine Abfrage darauf ausrichten kann.

+0

Okay, ich habe den ursprünglichen Beitrag so modifiziert, dass er eine modifizierte Version von dem enthält, für das ich vorgehe. Hoffentlich wird das helfen. –

Verwandte Themen