2012-04-16 21 views
5

Estoy intentando consultar una instancia de SQL Server para darme una lista de bases de datos que contienen una tabla con un nombre específico. Esto es lo que tengo hasta ahora ...¿Hay alguna forma de usar `exec` en una cláusula where?

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

Pero me sale el siguiente mensaje de error

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'. 

¿Cuál es la sintaxis correcta de utilizar llamar exec() en una cláusula where? ¿O hay otra forma de hacer lo que estoy tratando de hacer?

Respuesta

3

No, no puede usar exec en una cláusula where. ¿Qué tal algo de SQL dinámico:

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 poco más corto que el mío –

1

Esta instrucción SQL le dará todos los nombres de bases de datos que contienen la tabla que está buscando:

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

Tenga en cuenta que esta es una sp indocumentada. También obtiene un conjunto de resultados para cada base de datos, no un conjunto de resultados con todas las bases de datos relevantes en él. Está bien para las cosas de administración, lo hubiera pensado mucho antes de usarlo en el código de la aplicación. –

+0

De acuerdo! Supongo que la necesidad de buscar esquemas de bases de datos para una tabla era una necesidad del administrador. – schellack

+0

Me gusta que esta solución sea concisa, pero preferiría un conjunto de resultados en lugar de un conjunto de resultados para cada resultado. –

0

Usted tiene que usar tabla temporal para obtener información de vuelta del ejecutivo

Prueba este

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 fue construido para esto:

$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

¿Por qué es mejor ir a PowerShell en lugar de resolverlo desde T-SQL donde opera el OP? –

+0

Probablemente está bien en este caso, pero Powershell no está hecho para esto, si puedes hacerlo en dbms (dentro de lo razonable), deberías hacerlo. –

+0

¿Por qué? La falta de convolución en SQL dinámico. ¿Te das cuenta de que no tengo que saltar por los aros para escapar de las comillas? Además, MS ha dicho que powershell es el futuro de la administración. ¿Por qué no aprovechar todas las oportunidades para aplicarlo donde tenga sentido? Y creo que tiene sentido aquí. Por último, el OP dijo, y cito: "¿O hay otra manera de hacer lo que estoy tratando de hacer?". Por qué sí, sí, hay. –

0

También puede almacenar los resultados del procedimiento almacenado en una tabla temporal, y luego añadirlo a la cláusula WHERE