2012-04-16 10 views
5

Sto tentando di eseguire una query su un'istanza di SQL Server per fornirmi un elenco di database che contengono una tabella con un nome specifico. Questo è ciò che ho finora ...C'è un modo per usare `exec` in una clausola where?

select name 
from master..sysdatabases 
where (exec('use ' + name + '; select 1 from information_schema.tables 
    where table_name = ''TheTableName'';')) = 1; 

Ma io ottenere i seguenti messaggi di errore

Msg 156, Level 15, State 1, Line 4 
Incorrect syntax near the keyword 'exec'. 
Msg 102, Level 15, State 1, Line 4 
Incorrect syntax near 'name'. 

Qual è la sintassi corretta da utilizzare chiamare exec() in una clausola dove? O c'è un altro modo per fare ciò che sto cercando di fare?

risposta

3

No, non è possibile utilizzare exec in una clausola where. Che ne dite di un po 'di SQL dinamico:

DECLARE @sql NVARCHAR(MAX); 

SET @sql = N'SELECT name = NULL WHERE 1 = 0'; 

SELECT @sql = @sql + N' 
    UNION ALL SELECT name = ''' + name + ''' 
    WHERE EXISTS (SELECT 1 FROM ' + QUOTENAME(name) 
    + '.sys.tables WHERE name = ''TheTableName'')' 
    FROM sys.databases; 

EXEC sp_executesql @sql; 
+0

Hmmm un po 'più corto del mio –

1

Questa istruzione SQL vi darà tutti i nomi dei database che contengono la tabella che sono alla ricerca di:

EXEC sp_MSForEachDB 'USE [?]; select ''?'' from information_schema.tables where table_name = ''TheTableName''' ; 
+0

Tenete a mente che questo è uno sp non documentato. Inoltre si ottiene un set di risultati per ogni database, non un set di risultati con tutti i database rilevanti in esso contenuti. Va bene per le cose da amministratore, avrei pensato a fondo prima di usarlo nel codice dell'applicazione però. –

+0

D'accordo! Suppongo che la necessità di cercare tra gli schemi di database per una tabella fosse un'esigenza dell'amministratore. – schellack

+0

Mi piace che questa soluzione sia concisa, ma preferirei un set di risultati piuttosto che un set di risultati per ogni risultato. –

0

Devi usare tabella temporanea per ottenere informazioni indietro da exec.

Prova questa

Create Table #TableLocations(DatabaseName varchar(255) not null) 
Declare @databaseName VarChar(255) 
Declare @QueryString VarChar(255) 
Declare DatabaseNameCursor Cursor For Select [Name] From sys.databases 
Declare @TableName VarChar(255) 
Select @TableName = 'Put your table name here' 
Open DatabaseNameCursor 
Fetch Next From DatabaseNameCursor Into @databaseName 
While @@Fetch_Status = 0 
Begin 
    Select @QueryString = 'Use ' + @databaseName + ' Insert into #TableLocations Select ''' + @databaseName + ''' From information_schema.tables Where Table_Name = ''' + @TableName + '''' 
    Exec(@QueryString) 
    Fetch Next From DatabaseNameCursor Into @databaseName 
End 
Close DatabaseNameCursor 
DeAllocate DataBaseNameCursor 
Select * from #TableLocations 
Drop Table #TableLocations 
2

PowerShell è stata costruita per questo:

$server = new-object Microsoft.SqlServer.Management.Smo.Server "."; 
foreach ($db in $server.Databases) { 
    $t = $db.Tables | where {$_.Schema -eq 'YourSchema' -and $_.Name -eq 'TableName'}; 
    if ($t -ne $null) { 
     $db.Name; 
    } 
} 
+0

Perché è meglio andare su PowerShell invece di risolverlo da T-SQL in cui funziona l'OP? –

+0

Probabilmente va bene in questo caso, ma PowerShell non è stato creato per questo, se è possibile farlo nel dbms (entro limiti ragionevoli), è necessario. –

+0

Perché? Mancanza di convoluzione in SQL dinamico. Nota come non devo saltare attraverso i cerchi per sfuggire alle virgolette? Inoltre, MS ha affermato che PowerShell è il futuro dell'amministrazione. Perché non cogliere ogni occasione per applicarlo dove ha senso. E penso che abbia senso qui. Infine, l'OP ha detto, e cito: "O c'è un altro modo per fare ciò che sto cercando di fare?". Perché sì, sì, c'è. –

0

È anche possibile memorizzare i risultati dalla stored procedure in una tabella temporanea, e quindi inserirlo alla clausola WHERE