我想获得所有用户数据库的集合,每个数据库中的所有表,以及每个表的列及其数据类型。我有一个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 +。
答案 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