如何在SQL Server中的所有数据库中查找所有表的列名

How to find column names for all tables in all databases in SQL Server

我想在所有数据库的所有表中查找所有列名。有什么问题可以帮我解决吗?数据库是Microsoft SQL Server 2000。


试试这个:

1
2
3
4
5
SELECT
    o.name,c.name
    FROM sys.columns            c
        INNER JOIN sys.objects  o ON c.object_id=o.object_id
    ORDER BY o.name,c.column_id

对于生成的列名,这将是:

1
2
3
4
5
6
SELECT
     o.name AS [TABLE], c.name AS [COLUMN]
     FROM sys.columns            c
         INNER JOIN sys.objects  o ON c.object_id=o.object_id
     --where c.name = 'column you want to find'
     ORDER BY o.name,c.name

或者更详细地说:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
SELECT
    s.name AS ColumnName
        ,sh.name+'.'+o.name AS ObjectName
        ,o.type_desc AS ObjectType
        ,CASE
             WHEN t.name IN ('char','varchar') THEN t.name+'('+CASE WHEN s.max_length<0 THEN 'MAX' ELSE CONVERT(VARCHAR(10),s.max_length) END+')'
             WHEN t.name IN ('nvarchar','nchar') THEN t.name+'('+CASE WHEN s.max_length<0 THEN 'MAX' ELSE CONVERT(VARCHAR(10),s.max_length/2) END+')'
            WHEN t.name IN ('numeric') THEN t.name+'('+CONVERT(VARCHAR(10),s.precision)+','+CONVERT(VARCHAR(10),s.scale)+')'
             ELSE t.name
         END AS DataType

        ,CASE
             WHEN s.is_nullable=1 THEN 'NULL'
            ELSE 'NOT NULL'
        END AS NULLABLE
        ,CASE
             WHEN ic.column_id IS NULL THEN ''
             ELSE ' identity('+ISNULL(CONVERT(VARCHAR(10),ic.seed_value),'')+','+ISNULL(CONVERT(VARCHAR(10),ic.increment_value),'')+')='+ISNULL(CONVERT(VARCHAR(10),ic.last_value),'null')
         END
        +CASE
             WHEN sc.column_id IS NULL THEN ''
             ELSE ' computed('+ISNULL(sc.definition,'')+')'
         END
        +CASE
             WHEN cc.object_id IS NULL THEN ''
             ELSE ' check('+ISNULL(cc.definition,'')+')'
         END
            AS MiscInfo
    FROM sys.columns                           s
        INNER JOIN sys.types                   t ON s.system_type_id=t.user_type_id AND t.is_user_defined=0
        INNER JOIN sys.objects                 o ON s.object_id=o.object_id
        INNER JOIN sys.schemas                sh ON o.schema_id=sh.schema_id
        LEFT OUTER JOIN sys.identity_columns  ic ON s.object_id=ic.object_id AND s.column_id=ic.column_id
        LEFT OUTER JOIN sys.computed_columns  sc ON s.object_id=sc.object_id AND s.column_id=sc.column_id
        LEFT OUTER JOIN sys.check_constraints cc ON s.object_id=cc.parent_object_id AND s.column_id=cc.parent_column_id
    ORDER BY sh.name+'.'+o.name,s.column_id

编辑下面是获取所有数据库中所有列的基本示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
DECLARE @SQL VARCHAR(MAX)
SET @SQL=''
SELECT @SQL=@SQL+'UNION
select
'
''+d.name+'.''+sh.name+''.''+o.name,c.name,c.column_id
from '
+d.name+'.sys.columns            c
    inner join '
+d.name+'.sys.objects  o on c.object_id=o.object_id
    INNER JOIN '
+d.name+'.sys.schemas  sh on o.schema_id=sh.schema_id
'

FROM sys.databases d
SELECT @SQL=RIGHT(@SQL,LEN(@SQL)-5)+'order by 1,3'
--print @SQL
EXEC (@SQL)

编辑SQL Server 2000版本

1
2
3
4
5
6
7
8
9
10
11
12
13
DECLARE @SQL VARCHAR(8000)
SET @SQL=''
SELECT @SQL=@SQL+'UNION
select
'
''+d.name+'.''+sh.name+''.''+o.name,c.name,c.colid
from '
+d.name+'..syscolumns            c
    inner join sysobjects  o on c.id=o.id
    INNER JOIN sysusers  sh on o.uid=sh.uid
'

FROM master.dbo.sysdatabases d
SELECT @SQL=RIGHT(@SQL,LEN(@SQL)-5)+'order by 1,3'
--print @SQL
EXEC (@SQL)

编辑根据一些评论,这里有一个使用sp_MSforeachdb的版本:

1
2
3
4
5
6
sp_MSforeachdb 'select
    '
'?'' AS DatabaseName, o.name AS TableName,c.name AS ColumnName
    from sys.columns            c
        inner join ?.sys.objects  o on c.object_id=o.object_id
    --WHERE '
'?'' NOT IN (''master'',''msdb'',''tempdb'',''model'')
    order by o.name,c.column_id'


1
2
3
SELECT *
FROM information_schema.columns
WHERE column_name = 'My_Column'

在此查询之前,必须使用USE [db_name]设置当前数据库名称。


为什么不使用

1
SELECT * FROM INFORMATION_SCHEMA.COLUMNS

你可以用特定的

1
SELECT * FROM DBNAME.INFORMATION_SCHEMA.COLUMNS


更好的方法

1
2
3
4
5
6
7
8
9
10
sp_MSForEachDB @command1='USE ?;
SELECT
    Table_Catalog
    ,Table_Schema
    ,Table_Name
    ,Column_Name
    ,Data_Type
    ,Character_Maximum_Length
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME like '
'%ColumnNameHere%'''


1
2
3
SELECT sys.columns.name AS ColumnName, TABLES.name AS TableName
FROM sys.columns
     JOIN sys.tables ON sys.columns.object_id = TABLES.object_id


我刚刚意识到,下面的查询将为您提供数据库中表中的所有列名(SQL Server 2017)

1
2
SELECT DISTINCT NAME FROM SYSCOLUMNS
ORDER BY Name

或者简单地说

1
SELECT Name FROM SYSCOLUMNS

如果你不在乎重复的名字。

另一种选择是从INFORMATION_SCHEMA中选择列名称。

1
2
SELECT DISTINCT column_name  FROM INFORMATION_SCHEMA.COLUMNS
ORDER BY column_name

通常情况下,更有趣的是让表名以及下面的查询中的columnname Ant这样做。

1
2
3
4
SELECT
   Object_Name(Id) AS TableName,
   Name AS ColumnName
FROM SysColumns

结果是

1
2
3
4
5
6
  TableName    ColumnName
0    Table1    column11
1    Table1    Column12
2    Table2    Column21
3    Table2    Column22
4    Table3    Column23


尝试下面的查询

1
2
3
4
5
6
7
8
9
10
DECLARE @Query VARCHAR(MAX)
SELECT @Query = 'USE ? SELECT ''?'' AS DataBaseName,
                                sys.columns.name AS ColumnName  ,
                                sys.tables.name  AS TableName   ,
                                schema_name (sys.tables.schema_Id) AS schemaName
                         FROM sys.columns
                         JOIN sys.tables
              ON sys.columns.object_id = sys.tables.object_id
              WHERE sys.columns.name = '
'id'' '
EXEC SP_MSFOREACHDB @Query

提供包含来自所有数据库的ID列的表的列表。


一些小的改进

->以前的答案没有显示所有结果

->可以通过设置列名变量来筛选列名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
DECLARE @columnname nvarchar(150)
SET @columnname=''

DECLARE @SQL VARCHAR(MAX)
SET @SQL=''
SELECT @SQL=@SQL+'UNION
select
'
''+d.name+'.''+sh.name+''.''+o.name COLLATE SQL_Latin1_General_CP1_CI_AS as name,c.name COLLATE SQL_Latin1_General_CP1_CI_AS as columnname,c.column_id
from '
+d.name+'.sys.columns            c
    inner join '
+d.name+'.sys.objects  o on c.object_id=o.object_id
    INNER JOIN '
+d.name+'.sys.schemas  sh on o.schema_id=sh.schema_id
    where c.name like '
'%'+@columnname+'%'' and sh.name<>''sys''
'

FROM sys.databases d
SELECT @SQL=RIGHT(@SQL,LEN(@SQL)-5)+'order by 1,3'
--print @SQL
EXEC (@SQL)


感谢所有的帖子和评论,有些很好,但有些更好。

第一个大脚本很好,因为它提供了所需的内容。最快和最详细的建议是从信息中选择"schema.columns."。

我需要找到几乎相同名称和几个数据库的所有出错列。Sooo,我做了我的两个版本(见下文)…下面的两个脚本中的任何一个都可以工作并在几秒钟内交付货物。

在这个链接的其他文章中,假设第一个代码示例可以成功地用于每个数据库,这对我来说是不可取的。这是因为信息在特定的数据库中,"fedb"的简单使用不会产生正确的结果,它只是不提供访问权。因此,我使用一个光标来收集数据库,忽略那些离线的数据库,在本例中,这是一个实用程序脚本,很好地使用了它们。

总之,我读了每个人的帖子,把所有的文章更正了起来,并写出了另外两篇精彩的文章。我在下面列出了这两个文件,并将脚本文件放在OneDrive.com的公用文件夹中,您可以通过以下链接访问:http://1drv.ms/1vr8ynx

享受吧!汉克·弗里曼

高级-SQL Server DBA-数据架构师

分开试试……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
---------------------------
--- 1st example (works) ---
---------------------------
DECLARE
 @DBName sysname
,@SQL_String1 nvarchar(4000)
,@SQL_String2 nvarchar(4000)
,@ColumnName nvarchar(200)
--set @ColumnName = 'Course_ID'
-------- Like Trick --------
-- IF you want to add more the @ColumnName so it looks like Course_ID,CourseID
-- then add an additional pairing of +''','''+'NewColumnSearchIDValue'
----------------------------
SET @ColumnName = 'Course_ID' +''','''+'CourseID'
--select @ColumnName
-----
DECLARE @Column_Info TABLE
(
[DatabaseName] nvarchar(128) NULL,
[ColumnName] sysname NULL,
[ObjectName] nvarchar(257) NOT NULL,
[ObjectType] nvarchar(60) NULL,
[DataType] nvarchar(151) NULL,
[NULLABLE] VARCHAR(8) NOT NULL,
[MiscInfo] nvarchar(MAX) NOT NULL
)
--------------
BEGIN
    SET @SQL_String2 = 'SELECT
     DB_NAME() as '
'DatabaseName'',
    s.name as ColumnName
        ,sh.name+'
'.''+o.name AS ObjectName
        ,o.type_desc AS ObjectType
        ,CASE
             WHEN t.name IN ('
'char'',''varchar'') THEN t.name+''(''+CASE WHEN s.max_length<0 then ''MAX'' ELSE CONVERT(varchar(10),s.max_length) END+'')''
             WHEN t.name IN ('
'nvarchar'',''nchar'') THEN t.name+''(''+CASE WHEN s.max_length<0 then ''MAX'' ELSE CONVERT(varchar(10),s.max_length/2) END+'')''
            WHEN t.name IN ('
'numeric'') THEN t.name+''(''+CONVERT(varchar(10),s.precision)+'',''+CONVERT(varchar(10),s.scale)+'')''
             ELSE t.name
         END AS DataType
        ,CASE
             WHEN s.is_nullable=1 THEN '
'NULL''
            ELSE '
'NOT NULL''
        END AS Nullable
        ,CASE
             WHEN ic.column_id IS NULL THEN '
'''
             ELSE '
' identity(''+ISNULL(CONVERT(varchar(10),ic.seed_value),'''')+'',''+ISNULL(CONVERT(varchar(10),ic.increment_value),'''')+'')=''+ISNULL(CONVERT(varchar(10),ic.last_value),''null'')
         END
        +CASE
             WHEN sc.column_id IS NULL THEN '
'''
             ELSE '
' computed(''+ISNULL(sc.definition,'''')+'')''
         END
        +CASE
             WHEN cc.object_id IS NULL THEN '
'''
             ELSE '
' check(''+ISNULL(cc.definition,'''')+'')''
         END
            AS MiscInfo
    into ##Temp_Column_Info
    FROM sys.columns                           s
        INNER JOIN sys.types                   t ON s.system_type_id=t.user_type_id and t.is_user_defined=0
        INNER JOIN sys.objects                 o ON s.object_id=o.object_id
        INNER JOIN sys.schemas                sh on o.schema_id=sh.schema_id
        LEFT OUTER JOIN sys.identity_columns  ic ON s.object_id=ic.object_id AND s.column_id=ic.column_id
        LEFT OUTER JOIN sys.computed_columns  sc ON s.object_id=sc.object_id AND s.column_id=sc.column_id
        LEFT OUTER JOIN sys.check_constraints cc ON s.object_id=cc.parent_object_id AND s.column_id=cc.parent_column_id
    --------------------------------------------
    --- DBA - Hank 12-Feb-2015 added this specific where statement
    --     where Upper(s.name) like '
'COURSE%''
    --   where Upper(s.name) in ('
'' + @ColumnName + ''')
    --  where Upper(s.name) in ('
'cycle_Code'')
    -- ORDER BY sh.name+'
'.''+o.name,s.column_id
    order by 1,2'

--------------------
    DECLARE DB_cursor CURSOR
    FOR
         SELECT  name  FROM sys.databases
        --select * from sys.databases
        WHERE STATE = 0  
      --  and Name not IN ('master','msdb','tempdb','model','DocxPress')
        AND Name NOT IN ('msdb','tempdb','model','DocxPress')
    OPEN DB_cursor
    Fetch NEXT FROM DB_cursor INTO @DBName
    While @@FETCH_STATUS = 0
    BEGIN
        --select @DBName as '@DBName';
          SET @SQL_String1 = 'USE [' + @DBName + ']'
          SET @SQL_String1 = @SQL_String1 + @SQL_String2
          EXEC sp_executesql @SQL_String1;
        --
        INSERT INTO @Column_Info
        SELECT * FROM ##Temp_Column_Info;
        DROP TABLE ##Temp_Column_Info;
        Fetch NEXT FROM DB_cursor INTO @DBName
    END
    CLOSE DB_cursor;
    Deallocate DB_cursor;
    ---
    SELECT * FROM @Column_Info ORDER BY 2,3

----------------------------
END
---------------------------

Below IS the SECOND script..
---------------------------
--- 2nd example (works) ---
---------------------------
-- This is by far the best/fastes of the lot for what it delivers.
--Select * into dbo.hanktst From Master.INFORMATION_SCHEMA.COLUMNS
--FileID: SCRIPT_Get_Column_info_(INFORMATION_SCHEMA.COLUMNS).sql
----------------------------------------
--FileID: SCRIPT_Get_Column_info_(INFORMATION_SCHEMA.COLUMNS).sql
-- Utility to find all columns in all databases or find specific with a like statement
-- Look at this line to find a: --> set @SQL_String2 = ' select * into ##Temp_Column_Info....
----------------------------------------
---
SET NOCOUNT ON
BEGIN
 DECLARE @hanktst TABLE (
    [TABLE_CATALOG]              NVARCHAR(128) NULL
   ,[TABLE_SCHEMA]               NVARCHAR(128) NULL
   ,[TABLE_NAME]                 sysname NOT NULL
   ,[COLUMN_NAME]                sysname NULL
   ,[ORDINAL_POSITION]           INT NULL
   ,[COLUMN_DEFAULT]             NVARCHAR(4000) NULL
   ,[IS_NULLABLE]                VARCHAR(3) NULL
   ,[DATA_TYPE]                  NVARCHAR(128) NULL
   ,[CHARACTER_MAXIMUM_LENGTH]   INT NULL
   ,[CHARACTER_OCTET_LENGTH]     INT NULL
   ,[NUMERIC_PRECISION]          TINYINT NULL
   ,[NUMERIC_PRECISION_RADIX]    SMALLINT NULL
   ,[NUMERIC_SCALE]              INT NULL
   ,[DATETIME_PRECISION]         SMALLINT NULL
   ,[CHARACTER_SET_CATALOG]      sysname NULL
   ,[CHARACTER_SET_SCHEMA]       sysname NULL
   ,[CHARACTER_SET_NAME]         sysname NULL
   ,[COLLATION_CATALOG]          sysname NULL
   ,[COLLATION_SCHEMA]           sysname NULL
   ,[COLLATION_NAME]             sysname NULL
   ,[DOMAIN_CATALOG]             sysname NULL
   ,[DOMAIN_SCHEMA]              sysname NULL
   ,[DOMAIN_NAME]                sysname NULL
   )
       DECLARE
      @DBName sysname
      ,@SQL_String2 nvarchar(4000)
      ,@TempRowCnt VARCHAR(20)
      ,@Dbug bit = 0
      DECLARE DB_cursor CURSOR
      FOR
           SELECT  name  FROM sys.databases
          WHERE STATE = 0  
        --  and Name not IN ('master','msdb','tempdb','model','DocxPress')
          AND Name NOT IN ('msdb','tempdb','model','DocxPress')
      OPEN DB_cursor
      Fetch NEXT FROM DB_cursor INTO @DBName
      While @@FETCH_STATUS = 0
        BEGIN
        SET @SQL_String2 = ' select * into ##Temp_Column_Info from [' + @DBName + '].INFORMATION_SCHEMA.COLUMNS
        where UPPER(Column_Name) like '
'COURSE%''
        ;'

          IF @Dbug = 1  SELECT @SQL_String2 AS '@SQL_String2';
          EXEC sp_executesql @SQL_String2;
          INSERT INTO @hanktst
          SELECT * FROM ##Temp_Column_Info;
          DROP TABLE ##Temp_Column_Info;
         Fetch NEXT FROM DB_cursor INTO @DBName
        END
        SELECT * FROM @hanktst ORDER BY 4,2,3
      CLOSE DB_cursor;
      Deallocate DB_cursor;
      SET @TempRowCnt = (SELECT CAST(COUNT(1) AS VARCHAR(10)) FROM @hanktst )
       Print ('Rows found: '+ @TempRowCnt +'  end ...')
END  
--------


通常,我会尽我所能避免使用光标,但下面的查询将为您提供所需的一切:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
--Declare/Set required variables
DECLARE @vchDynamicDatabaseName AS VARCHAR(MAX),
        @vchDynamicQuery AS VARCHAR(MAX),
        @DatabasesCursor CURSOR

SET @DatabasesCursor = Cursor FOR

--Select * useful databases on the server
SELECT name
FROM sys.databases
WHERE database_id > 4
ORDER BY name

--Open the Cursor based on the previous select
OPEN @DatabasesCursor
FETCH NEXT FROM @DatabasesCursor INTO @vchDynamicDatabaseName
WHILE @@FETCH_STATUS = 0
   BEGIN

   --Insert the select statement into @DynamicQuery
   --This query will select the Database name, all tables/views and their columns (in a comma delimited field)
   SET @vchDynamicQuery =
   ('SELECT ''' + @vchDynamicDatabaseName + ''' AS ''Database_Name'',
          B.table_name AS '
'Table Name'',
         STUFF((SELECT '
', '' + A.column_name
               FROM '
+ @vchDynamicDatabaseName + '.INFORMATION_SCHEMA.COLUMNS A
               WHERE A.Table_name = B.Table_Name
               FOR XML PATH('
'''),TYPE).value(''(./text())[1]'',''NVARCHAR(MAX)'')
               , 1, 2, '
''') AS ''Columns''
   FROM '
+ @vchDynamicDatabaseName + '.INFORMATION_SCHEMA.COLUMNS B
   WHERE B.TABLE_NAME LIKE '
'%%''
         AND B.COLUMN_NAME LIKE '
'%%''
   GROUP BY B.Table_Name
   Order BY 1 ASC'
)

   --Print @vchDynamicQuery
   EXEC(@vchDynamicQuery)

   FETCH NEXT FROM @DatabasesCursor INTO @vchDynamicDatabaseName
END
CLOSE @DatabasesCursor
DEALLOCATE @DatabasesCursor
GO

我在主查询中添加了一个WHERE子句(如"%%",b.table_name如"%%",b.column_name如"%%"),这样您可以根据需要搜索特定的表和/或列。


用户@km说出最佳答案。

我用这个:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
DECLARE @TABLE_NAME VARCHAR(100) ,@Column_Name VARCHAR(100)
SET @TABLE_NAME = ''
SET @Column_Name = ''

SELECT
RowNumber = ROW_NUMBER() OVER( PARTITION BY T.[Name] ORDER BY T.[Name],C.column_id  ),
SCHEMA_NAME( T.schema_id ) AS SchemaName ,  
T.[Name] AS TABLE_NAME ,
C.[Name] AS Field_Name ,
sysType.name ,
C.max_length , C.is_nullable , C.is_identity , C.scale , C.precision  
FROM Sys.Tables AS T
LEFT JOIN Sys.Columns AS C ON ( T.[Object_Id] = C.[Object_Id] )
LEFT JOIN sys.types AS sysType ON ( C.user_type_id = sysType.user_type_id )
WHERE ( TYPE = 'U' )
    AND ( C.Name LIKE '%' + @Column_Name + '%' )  
    AND ( T.Name LIKE '%' + @TABLE_NAME + '%' )


对KM的解决方案进行了细微的改进,适用于像我这样的在DB服务器上享受排序乐趣的人……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
DECLARE @SQL VARCHAR(MAX)=''

SELECT @SQL=@SQL+'UNION
select
'
''+d.name +'.''+sh.name+''.''+o.name COLLATE SQL_Latin1_General_CP1_CI_AS,c.name COLLATE SQL_Latin1_General_CP1_CI_AS,c.column_id
from '
+d.name +'.sys.columns            c
    inner join sys.objects  o on c.object_id=o.object_id
    INNER JOIN sys.schemas  sh on o.schema_id=sh.schema_id
'

FROM sys.databases d

SELECT @SQL=RIGHT(@SQL,LEN(@SQL)-5)+'order by 1,3'
--print @SQL

EXEC (@SQL)

(仍然生活在希望我们能找到一种方法做到这一点,并将其包装成一个视图。)