¡Hola, chicos!
Todo está en calma, ¿verdad?
Hoy les mostraré cómo ejecutar una consulta en todas las bases de datos en una instancia de SQL Server. Esto suele ser útil para crear rutinas de monitoreo de espacio, ejecutar una base de datos de verificación en todos los bancos y muchas otras necesidades diarias.
Para realizar esta actividad existen varias formas diferentes de programar, pero yo abordaré dos de las más utilizadas.
sp_MSforeachdb
El procedimiento sp_MSforeachdb ya viene por defecto en SQL Server, pero no cuenta con documentación oficial de Microsoft por el momento y por lo tanto, muchas personas desconocen su existencia o cómo utilizarlo. Uno de los detalles más importantes en su uso es el comodín ?, el cual recibirá el nombre de la base de datos que está siendo iterada por el Procedimiento Almacenado sp_MSforeachdb.
Veamos un ejemplo muy básico que solo mostrará el nombre de cada base de datos:
EXEC master.sys.sp_MSforeachdb '
USE [?]
SELECT DB_NAME()'
Mostrar los archivos de datos para cada base de datos
EXEC master.sys.sp_MSforeachdb 'SELECT * FROM [?].sys.database_files'
Mostrando los archivos de datos de cada base de datos que contiene la palabra “Cobranca”
EXEC master.sys.sp_MSforeachdb '
IF (''[?]'' LIKE ''%Cobranca%'')
SELECT * FROM [?].sys.database_files
'
Mostrar el nombre de las bases de datos, esquemas y tablas que comienzan con Cliente en su instancia
EXEC master.sys.sp_MSforeachdb '
USE [?];
IF((SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = ''Cliente'') > 0)
BEGIN
SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE ''Cliente%''
END'
Uso de vistas del catálogo de SQL Server
El procedimiento del sistema sp_MSforeachdb es muy útil en el día a día de un DBA y es muy fácil de usar, pero he visto algunos casos en los que la base de datos ignora algunas bases de datos durante la iteración cuando hay una sobrecarga muy grande en el servidor. Por lo tanto, mostraré otro enfoque para satisfacer esta necesidad.
Ejemplo 1:
IF (OBJECT_ID('tempdb..#Databases') IS NOT NULL) DROP TABLE #Databases
SELECT [name], [dbid], IDENTITY(INT, 1, 1) AS Ordem
INTO #Databases
FROM sys.sysdatabases WITH(NOLOCK)
ORDER BY name
DECLARE
@Qt_Databases INT = (SELECT COUNT(*) FROM #Databases),
@Contador INT = 1,
@Ds_Database SYSNAME,
@Ds_Query VARCHAR(MAX) = 'SELECT * FROM sys.database_files',
@Cmd VARCHAR(MAX)
WHILE(@Contador <= @Qt_Databases)
BEGIN
SELECT @Ds_Database = name
FROM #Databases
WHERE Ordem = @Contador
SET @Cmd = 'USE [' + @Ds_Database + ']; ' + CHAR(10) + @Ds_Query
EXEC(@Cmd)
SET @Contador = @Contador + 1
END
Ejemplo 2:
Después de crear el SP a continuación, devuelve el nombre de todas las bases de datos y las escribe en una tabla temporal.
IF (OBJECT_ID('tempdb..#Dbs') IS NOT NULL) DROP TABLE #Dbs
CREATE TABLE #Dbs (
Nome SYSNAME
)
INSERT INTO #Dbs
EXEC dbo.stpExecuta_Query_Databases
@Ds_Query = 'SELECT DB_NAME()'
Devuelve el nombre de todas las bases de datos que contienen “Cobranca” en el nombre
EXEC dbo.stpExecuta_Query_Databases
@Ds_Query = 'SELECT DB_NAME()',
@Ds_Incluir_Database = '%Cobranca%'
Devuelve el nombre de todas las bases de datos que NO contienen “Cobranca” en el nombre
EXEC dbo.stpExecuta_Query_Databases
@Ds_Query = 'SELECT DB_NAME()',
@Ds_Excluir_Database = '%Cobranca%'
Código de procedimiento almacenado stpExecut_Query_Databases:
CREATE PROCEDURE dbo.stpExecuta_Query_Databases (
@Ds_Query VARCHAR(MAX),
@Ds_Incluir_Database VARCHAR(MAX) = NULL,
@Ds_Excluir_Database VARCHAR(MAX) = NULL
)
AS BEGIN
IF (OBJECT_ID('tempdb..#Databases') IS NOT NULL) DROP TABLE #Databases
CREATE TABLE #Databases (
[name] SYSNAME,
[database_id] INT,
[Ordem] INT IDENTITY(1, 1)
)
IF (@Ds_Incluir_Database IS NULL AND @Ds_Excluir_Database IS NULL)
BEGIN
INSERT INTO #Databases
SELECT [name], [database_id]
FROM sys.databases WITH(NOLOCK)
WHERE state_desc = 'ONLINE'
ORDER BY name
END
ELSE BEGIN
IF (@Ds_Incluir_Database IS NOT NULL)
BEGIN
INSERT INTO #Databases
SELECT [name], [database_id]
FROM sys.databases WITH(NOLOCK)
WHERE [name] LIKE (@Ds_Incluir_Database)
AND state_desc = 'ONLINE'
ORDER BY name
END
ELSE BEGIN
INSERT INTO #Databases
SELECT [name], [database_id]
FROM sys.databases WITH(NOLOCK)
WHERE [name] NOT LIKE (@Ds_Excluir_Database)
AND state_desc = 'ONLINE'
ORDER BY name
END
END
DECLARE
@Qt_Databases INT = (SELECT COUNT(*) FROM #Databases),
@Contador INT = 1,
@Ds_Database SYSNAME,
@Cmd VARCHAR(MAX)
WHILE(@Contador <= @Qt_Databases)
BEGIN
SELECT @Ds_Database = name
FROM #Databases
WHERE Ordem = @Contador
SET @Cmd = 'USE [' + @Ds_Database + ']; ' + CHAR(10) + @Ds_Query
EXEC(@Cmd)
SET @Contador = @Contador + 1
END
END
Comentários (0)
Carregando comentários…