获取数据库,表,列和列数据类型的列表

时间:2017-11-15 17:29:50

标签: sql sql-server

我想获得所有用户数据库的集合,每个数据库中的所有表,以及每个表的列及其数据类型。我有一个SQL脚本,它获取我正在寻找的数据库名称(并排除我不喜欢的那些,如系统数据库)......

DECLARE @DatabaseIgnoreList AS VARCHAR(500);
SET @DatabaseIgnoreList = 'DatabaseNotToInclude';

SELECT name, database_id
FROM sys.databases 
WHERE HAS_DBACCESS(name) = 1 
AND name NOT IN ('msdb') 
AND database_id > 4 
AND name NOT LIKE '%$%' 
AND name NOT IN (@DatabaseIgnoreList)
ORDER BY name ASC

我还有一个单独的SQL脚本,可以从特定数据库中获取所有表和列。我是从this SO question/answer找到的。

USE DatabaseName;
SELECT TABLE_SCHEMA ,
   TABLE_NAME ,
   COLUMN_NAME ,
   ORDINAL_POSITION ,
   COLUMN_DEFAULT ,
   DATA_TYPE ,
   CHARACTER_MAXIMUM_LENGTH ,
   NUMERIC_PRECISION ,
   NUMERIC_PRECISION_RADIX ,
   NUMERIC_SCALE ,
   DATETIME_PRECISION
FROM INFORMATION_SCHEMA.COLUMNS;

我不知道怎么办才能将两者联系起来。对于每个数据库,我想运行表/列发现脚本,最后得到一个具有数据库名称,表名,列名和列数据类型的表。

这是游标的情况吗?我正在使用SQL Server 2008 +。

2 个答案:

答案 0 :(得分:2)

这是另一种方法。这不使用任何游标或循环。它是一个结果集,其中包含一个用于数据库名称的额外列。代码中有几条注释可以提供帮助。

FWIW - 我刚刚在拥有60个数据库的开发服务器上测试过它。它在15秒内返回了所有165,000多行。

DECLARE @DatabaseIgnoreList AS VARCHAR(500);
SET @DatabaseIgnoreList = 'DatabaseNotToInclude';

declare @SQL nvarchar(max) = ''

select @SQL = @SQL + 
    'SELECT ''' + quotename(name) + ''' as DatabaseName, 
       TABLE_SCHEMA  = TABLE_SCHEMA collate database_default,
       TABLE_NAME = TABLE_NAME COLLATE database_default ,
       COLUMN_NAME = COLUMN_NAME COLLATE database_default ,
       ORDINAL_POSITION ,
       COLUMN_DEFAULT = COLUMN_DEFAULT COLLATE database_default ,
       DATA_TYPE = DATA_TYPE COLLATE database_default ,
       CHARACTER_MAXIMUM_LENGTH ,
       NUMERIC_PRECISION ,
       NUMERIC_PRECISION_RADIX ,
       NUMERIC_SCALE ,
       DATETIME_PRECISION
    FROM ' + quotename(name) + '.INFORMATION_SCHEMA.COLUMNS union all '
FROM sys.databases 
WHERE HAS_DBACCESS(name) = 1 
    --AND name NOT IN ('msdb') --why bother? You already exclude this with database_id > 4
    AND database_id > 4 
    AND name NOT LIKE '%$%' 
    AND name <> @DatabaseIgnoreList --if you need to exclude more than 1 we need a little different approach here
    and state_desc = 'ONLINE' --want to exclude any offline databases
ORDER BY name ASC

set @SQL = left(@SQL, LEN(@SQL) - 10) + ' order by DatabaseName, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME' --This will order the entire result set

select @SQL
--uncomment the line below when you are satisfied the dynamic sql is correct
--exec sp_executesql @SQL

答案 1 :(得分:1)

这不是最好的方法,但它有效

  DECLARE @DatabaseIgnoreList AS VARCHAR(500);
  SET @DatabaseIgnoreList = 'DatabaseNotToInclude';

  SELECT name, database_id
  into #temporaltable
  FROM sys.databases 
  WHERE HAS_DBACCESS(name) = 1 
  AND name NOT IN ('msdb') 
  AND database_id > 4 
  AND name NOT LIKE '%$%' 
  AND name NOT IN (@DatabaseIgnoreList)
  ORDER BY name ASC






declare 
        @target varchar(250), 
        @statement varchar(max)

declare @schemas as CURSOR;

set @schemas = CURSOR FOR

select name from #temporaltable;

open @schemas;

fetch next from @schemas INTO @target

while @@FETCH_STATUS = 0

begin

    set @statement = '
    use '+@target+'

   SELECT TABLE_SCHEMA ,
   TABLE_NAME ,
   COLUMN_NAME ,
   ORDINAL_POSITION ,
   COLUMN_DEFAULT ,
   DATA_TYPE ,
   CHARACTER_MAXIMUM_LENGTH ,
   NUMERIC_PRECISION ,
   NUMERIC_PRECISION_RADIX ,
   NUMERIC_SCALE ,
   DATETIME_PRECISION,
   TABLE_CATALOG
   FROM INFORMATION_SCHEMA.COLUMNS'

    EXEC (@statement)

fetch next from @schemas INTO @target
end

close @schemas;
deallocate @schemas

drop table #temporaltable