La verdad es que es un poco fastidioso (por definirlo suavemente), que las funciones de sistema object_name, object_id, objectproperty, etc. estén bajo el ámbito de una base de datos…A mí me gustaría una función de este estilo: objec_name (db_id, object_id) , y me devolviera el nombre del identificador de objeto object_id, de la base de datos db_id.

Esto está tomando otros aires a partir de la versión 2005 de SQL Server, y ahora con las nuevas DMVs, el ámbito es más a nivel de instancia de SQL Server; por ejemplo, la DMV sys.dm_db_sys.dm_db_index_usage_stats, o la DMF sys.dm_db_index_physical_stats están definidas a nivel de instancia (fíjate que tiene como argumento el identificador de base de datos.

Entonces, ¿por qué no una función de sistema como object_name, cuyo ámbito sea la base de datos?

mientras eso no aparezca, podremos utilizar el siguiente código que explico a continuación:

la idea es muy simple: un cursor que se recorra todas las bases de datos de la instancia de SQL Server, y ejecutar una sentencia sql dinámica del siguiente formato:

INSERT INTO ##objetos (dbid, database_name, objectid, object_name, indexid, index_name, xtype)

SELECT dbid, db_name, so.id, so.name, si.indid, si.name, so.xtype FROM

<base_datos>..sysobjects so join

<base_datos>..sysindexes si on so.id = si.id WHERE so.id > 0

 

 

No hemos inventado la rueda… aunque estoy seguro que le podrás sacar provecho… adaptala a tu necesidad, y comentame si te sirve 😉

— obtener todos los dbid, objectid

SET NOCOUNT ON

GO

IF NOT OBJECT_ID (‘tempdb.dbo.##objetos’) IS NULL

 

DROP TABLE ##objetos

CREATE TABLE ##objetos (dbid INT, database_name SYSNAME, objectid INT, object_name SYSNAME, indexid INT, index_name SYSNAME NULL, xtype char(2))

DECLARE c1 CURSOR READ_ONLY

FOR SELECT dbid, name FROM master..sysdatabases where dbid >= 5

DECLARE @db_id SMALLINT

, @db_name SYSNAME

OPEN c1

FETCH NEXT FROM c1 INTO @db_id, @db_name

 

WHILE (@@fetch_status <> 1)

BEGIN

 

IF (@@fetch_status <> 2)

BEGIN

DECLARE @sql NVARCHAR(4000)

SET @sql = ‘INSERT INTO ##objetos (dbid, database_name, objectid, object_name, indexid, index_name, xtype) ‘

SET @sql = @sql + ‘SELECT ‘ + CAST(@db_id AS SYSNAME) + ‘, »’ + CAST(@db_name AS SYSNAME)

+ »’, so.id, so.name, si.indid, si.name, so.xtype FROM ‘ +

@db_name + ‘..sysobjects so join ‘ +

@db_name + ‘..sysindexes si on so.id = si.id WHERE so.id > 0’

EXEC (@sql)

END

FETCH NEXT FROM c1 INTO @db_id, @db_name

END

CLOSE c1

DEALLOCATE c1

 

 

Ahora ya solo quedaría consulta la tabla rellena:

SELECT * FROM ##objetos

 

Por cierto, aplicable para cualquier versión de SQL Server… para 2005 sería didáctico hacerlo con las nuevas DMVs (sys.tables, sys.objects, …), pero bueno, lo dejamos como ejercicio 🙂

Eladio Rincón