выбрать все базы данных в sysobjects, которые имеют таблицу с именем «mytable», независимо от схемы?

Для данного сервера sql 2000–2008 я хочу найти любую таблицу с именем dbo.[MyTable] на этом сервере. Кроме того, как найти все базы данных, в которых есть таблица с именами [dbo].[MyTable] и [AnySchemaName].[MyTable]. Есть ли простая команда sp_, такая как spTables MyTable? Или «sp_AllDatabaseTable [MyTable]»?

Я хочу распечатать его так:

ServerName  Database  SchemaName  MyTable   Date Created
----------- --------- ----------- --------- -------------

Спасибо


person RetroCoder    schedule 02.12.2011    source источник
comment
Кроме того, в SQL Server 2005 и новее вы должны прекратить использовать sysobjects, поскольку он устарел - вместо этого используйте представления из схемы sys, например. SELECT name FROM sys.tables ... и так далее   -  person marc_s    schedule 03.12.2011


Ответы (4)


Конечно, вы можете использовать для этой цели sp_msforeachdb, но вы должны помнить, что эта функция не документирована и не поддерживается официально. К тому же иногда ломается. Подробнее об этом здесь Повышение надежности и гибкости sp_MSforeachdb

Вы можете использовать этот скрипт для поиска таблицы по имени во всех базах данных. Я взял его из Найти таблицу в каждой базе данных SQL сервера

DECLARE @TableName VARCHAR(256)
SET @TableName='YOUR_TABLE_NAME'
DECLARE @DBName VARCHAR(256)
DECLARE @varSQL VARCHAR(512)
DECLARE @getDBName CURSOR
SET @getDBName = CURSOR FOR
SELECT name
FROM sys.databases
CREATE TABLE #TmpTable (DBName VARCHAR(256),
SchemaName VARCHAR(256),
TableName VARCHAR(256),
create_date date, modify_date date)
OPEN @getDBName
FETCH NEXT
FROM @getDBName INTO @DBName
WHILE @@FETCH_STATUS = 0
BEGIN
SET @varSQL = 'USE ' + @DBName + ';
INSERT INTO #TmpTable
SELECT '''+ @DBName + ''' AS DBName,
SCHEMA_NAME(schema_id) AS SchemaName,
name AS TableName,
create_date, modify_date
FROM sys.tables
WHERE name LIKE ''%' + @TableName + '%''' --WHERE name = '' + @TableName + ''' /* if you want to search by exact table name*/ 
EXEC (@varSQL)
FETCH NEXT
FROM @getDBName INTO @DBName
END
CLOSE @getDBName
DEALLOCATE @getDBName
SELECT *
FROM #TmpTable
DROP TABLE #TmpTable

Кроме того, вы можете прочитать это Найти имя таблицы во всех объектах всех баз данных

person Igor Borisenko    schedule 04.12.2011

Я действительно предпочел бы решение, которое не использует ни CURSORS, ни sp_msforeachdb.

Приведенное ниже решение дает вам представление, и вы можете адаптировать его к своим потребностям.

USE [master]
GO


SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO


BEGIN TRY



SET NOCOUNT ON
SET DATEFORMAT DMY
SET DEADLOCK_PRIORITY NORMAL;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

DECLARE  @log NVARCHAR(MAX)
        ,@vCrlf CHAR(2);

SELECT  @log = ''
       ,@vCrlf = CHAR(13)+CHAR(10);


DECLARE @SQL NVARCHAR(MAX)

BEGIN TRY DROP TABLE #OBJECTS END TRY BEGIN CATCH END CATCH
CREATE TABLE #OBJECTS(
DB_ID INT,
OBJECT_ID INT,
S_NAME SYSNAME,
NAME SYSNAME,
ROW_COUNT INT,
STATISTICS_UPDATED DATETIME)




SELECT @SQL = '

SELECT db_id=db_id(),
       o.object_id,
       s_name=s.name,
       o.name,
       ddps.row_count 
       ,[Statistics_Updated]=STATS_DATE(I.OBJECT_ID,I.INDEX_ID)
FROM sys.indexes AS i
  INNER JOIN sys.objects AS o ON i.OBJECT_ID = o.OBJECT_ID
  INNER JOIN sys.schemas s ON s.schema_id = o.schema_id
  INNER JOIN sys.dm_db_partition_stats AS ddps ON i.OBJECT_ID = ddps.OBJECT_ID
  AND i.index_id = ddps.index_id 
WHERE i.index_id < 2  
 AND o.is_ms_shipped = 0

 '


set @SQL = (
            SELECT STUFF(
  (SELECT N'  ' + ' USE ' + QUOTENAME(name) +';' + @vCrlf + @SQL + @vCrlf    
                                FROM SYS.DATABASES SD
                                WHERE SD.STATE_DESC = 'ONLINE' -->Skips the database if it is not online
                                  AND SD.COMPATIBILITY_LEVEL > 80  
                                  AND SD.database_id > 3 -- NO MASTER NOR TEMPDB NOR MODEL
                        FOR XML PATH(''),TYPE)
  .value('text()[1]','nvarchar(max)'),1,2,N'')
)






INSERT INTO #OBJECTS
(   [db_id],
    [object_id],
    [s_name],
    [name],
    [row_count],
    [Statistics_Updated]
)
EXECUTE MASTER.DBO.sp_executesql @SQL

SELECT * FROM #OBJECTS
--WHERE NAME = 'THE NAME THAT I AM LOOKING FOR'

END TRY
BEGIN CATCH

        PRINT '--EXCEPTION WAS CAUGHT--' + CHAR(13) +
              'THE ERROR NUMBER:' + COALESCE(CAST ( ERROR_NUMBER()  AS VARCHAR), 'NO INFO') + CHAR(13) 

        PRINT 'SEVERITY: '        + COALESCE(CAST ( ERROR_SEVERITY()  AS VARCHAR), 'NO INFO') + CHAR(13) +
              'STATE: '           + COALESCE(CAST ( ERROR_STATE() AS VARCHAR), 'NO INFO')  + CHAR(13) 

        PRINT 'PROCEDURE: '       + COALESCE(CAST ( COALESCE(ERROR_PROCEDURE(),'NO INFO')  AS VARCHAR), 'NO INFO') + CHAR(13) +
              'LINE NUMBER: '     + COALESCE(CAST ( ERROR_LINE() AS VARCHAR), 'NO INFO')  + CHAR(13) 

        PRINT 'ERROR MESSAGE: '
        PRINT  CAST ( COALESCE(ERROR_MESSAGE(),'NO INFO')   AS NTEXT)

END CATCH;
person Marcello Miorelli    schedule 02.12.2014

Я предпочитаю подход на основе набора:

Declare @TableName as Varchar(255)
Set @TableName = '<MyTableName>'

Declare @SQL as Varchar(max)
Select @SQL = Coalesce(@SQL + '
', '') + 
CASE 
WHEN Row_Number() Over (Order by Database_ID) = 1 
THEN '' 
ELSE 
'UNION ALL ' 
END +
'SELECT 
  ''' + d.Name + '''    as DatabaseName
, s.Name                as SchemaName 
, o.Name                as TableName 
FROM ' + d.Name +'.Sys.Objects o 
INNER JOIN ' + d.Name + '.Sys.Schemas s
ON o.Schema_ID = s.Schema_ID
WHERE o.Name like ''' + @TableName + ''''
FROM sys.databases d
where d.Name not like 'ReportServer%'
and d.Name not like 'SSISPackageRegistry'

Print @SQL 
EXEC(@SQL)
person Karl Haberl    schedule 12.05.2015
comment
Какое преимущество имеет подход, основанный на наборах? Почему не процедурный? - person dbf; 13.05.2015

я бы сказал

sp_msforeachdb 'Select * from Sysobjects where name=''MyTable'''

Но вам это не нужно, sysobjects находится в главной таблице и в любом случае делает это для всех баз данных.

Вы должны быть в состоянии найти другие столбцы достаточно легко.

person Stephen Turner    schedule 02.12.2011