SQL Server:比较两个表中的列

时间:2010-03-11 20:05:53

标签: sql sql-server database

我最近完成了从某个应用程序的旧版本到当前版本的迁移,我在迁移数据库时遇到了一些问题。

我需要一个可以帮助我比较两个表中的列的查询。我的意思不是行中的数据,我需要比较列本身来弄清楚,我错过了表结构的哪些变化。

5 个答案:

答案 0 :(得分:12)

查看Red Gate SQL Compare

否则这是一个开始(对于sql server)

select 
 so.name as [table],
 sc.name as [column],
 sc.type, sc.length, sc.prec, sc.scale, sc.collation
from 
 sysobjects so
 inner join syscolumns sc ON so.id = sc.id

where so.type='u'

order by so.name, sc.colorder

你可以看看

 - INFORMATION_SCHEMA.TABLES
 - INFORMATION_SCHEMA.COLUMNS
 - INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
 - INFORMATION_SCHEMA.TABLE_CONSTRAINTS
 - INFORMATION_SCHEMA.KEY_COLUMN_USAGE

表如果你想深入..

[更新]

使用INFORMATION_SCHEMA表

SELECT
 [table].TABLE_NAME AS [Table_Name],
 [column].COLUMN_NAME AS [Column_Name],
 COLUMNPROPERTY(object_id([table].[TABLE_NAME]), [column].[COLUMN_NAME], 'IsIdentity') AS [identity],
 [column].DATA_TYPE AS [datatype],
 [column].CHARACTER_MAXIMUM_LENGTH AS [Character_Length],
 [column].NUMERIC_PRECISION AS Numeric_precision,
 [column].ORDINAL_POSITION AS [order],
 [column].COLUMN_DEFAULT AS [defaultvalue],
 [column].IS_NULLABLE AS [nullable]
FROM 
 INFORMATION_SCHEMA.TABLES [table] INNER JOIN 
 INFORMATION_SCHEMA.COLUMNS [column] ON [table].TABLE_NAME = [column].TABLE_NAME
WHERE
 [table].TABLE_TYPE = 'BASE TABLE'
 AND [table].TABLE_NAME <> 'sysdiagrams'
ORDER BY 
 [table].TABLE_NAME ASC, 
 [column].ORDINAL_POSITION ASC

答案 1 :(得分:8)

我真的建议您使用第三方比较工具,例如上面已经提到的SQL Compare或ApexSQL Diff或基本上市场上的任何其他工具。

即使这些是商业工具,如果您不需要每天都这样做,您可以获得免费试用并完成工作。

如果你真的需要使用SQL,你可以尝试这样简单的查询,然后在此基础上构建。

select T.name, C.*
from sys.tables T
inner join sys.columns C on T.object_id = C.object_id
where T.name = 'table_name'

答案 2 :(得分:6)

真的,这是一个很大的脚本。 :)

使用红门sql比较。他们为您提供14天免费试用

如果你真的需要脚本,它可以是一个文本,而不是你可以使用任何文本比较器进行比较。

答案 3 :(得分:5)

这适合我(有同样的问题,只是编译了我的解决方案)

DECLARE @TableOne VARCHAR(2048) = '',
        @TableTwo VARCHAR(2048) = ''

-- In TableOne but not in TableTwo
SELECT DISTINCT
       @TableOne AS [First table],
       '>>' AS Dir, --Direction
       @TableTwo AS [Second table],
       a.COLUMN_NAME,
       a.DATA_TYPE         
  FROM INFORMATION_SCHEMA.COLUMNS a
 WHERE a.COLUMN_NAME NOT IN (SELECT COLUMN_NAME
                               FROM INFORMATION_SCHEMA.COLUMNS b
                              WHERE b.TABLE_NAME = @TableTwo)
   AND a.TABLE_NAME = @TableOne
UNION ALL
-- In TableTwo but not in TableOne
SELECT DISTINCT
       @TableOne AS [First table],
       '<<' AS Dir, --Direction
       @TableTwo AS [Second table],
       a.COLUMN_NAME,
       a.DATA_TYPE         
  FROM INFORMATION_SCHEMA.COLUMNS a
 WHERE a.COLUMN_NAME NOT IN (SELECT COLUMN_NAME
                               FROM INFORMATION_SCHEMA.COLUMNS b
                              WHERE b.TABLE_NAME = @TableOne)
   AND a.TABLE_NAME = @TableTwo
 ORDER BY Dir DESC, COLUMN_NAME ASC

只需为@TableOne和@TableTwo设置值并运行脚本;)

答案 4 :(得分:0)

我发现Qcpbraca的解决方案与我正在寻找的解决方案最相符,但至少从我的角度来看,它觉得从视觉上看结果有点困难,并且知道缺少哪一列。我也经常有列名匹配,但数据类型不匹配,因此我也将其添加到下面的代码中。

以下脚本在Qcpbraca脚本的基础上进行了扩展,因此,如果您认为这对投票有帮助,请考虑同时投票Qcpbraca的答案。

DECLARE @Table1 VARCHAR(2048) = 'Table_1',
        @Table2 VARCHAR(2048) = 'Table_2'

-- Table 1 Columns into #temp_table_1
SELECT DISTINCT
       a.COLUMN_NAME AS [Column Name],
       a.DATA_TYPE as [Data Type],
       a.CHARACTER_MAXIMUM_LENGTH,
       a.NUMERIC_PRECISION,
       a.NUMERIC_SCALE
into #temp_table1
FROM INFORMATION_SCHEMA.COLUMNS a
where a.TABLE_NAME = @Table1
order by a.COLUMN_NAME

-- Table 2 Columns into #temp_table_2
SELECT DISTINCT
       a.COLUMN_NAME AS [Column Name],
       a.DATA_TYPE as [Data Type],
       a.CHARACTER_MAXIMUM_LENGTH,
       a.NUMERIC_PRECISION,
       a.NUMERIC_SCALE
into #temp_table2
FROM INFORMATION_SCHEMA.COLUMNS a
where a.TABLE_NAME = @Table2
order by a.COLUMN_NAME

select 
    @Table1 [Table 1],
    isnull(t1.[Column Name],'') [Table 1 Column Name],
    isnull(t2.[Column Name],'') [Table 2 Column Name],
    @Table2 [Table 2],
    isnull(t1.[Data Type],'') [Table 1 Column Type],
    isnull(t2.[Data Type],'') [Table 2 Column Type],
    isnull(cast(t1.CHARACTER_MAXIMUM_LENGTH as varchar(50)),isnull(cast(t1.NUMERIC_PRECISION as varchar(50)),'') + ',' +
        isnull(cast(t1.NUMERIC_SCALE as varchar(50)),'')) [Table 1 Column Precision],
    isnull(cast(t2.CHARACTER_MAXIMUM_LENGTH as varchar(50)),isnull(cast(t2.NUMERIC_PRECISION as varchar(50)),'') + ',' +
        isnull(cast(t2.NUMERIC_SCALE as varchar(50)),'')) [Table 2 Column Precision],
    --[Data Type Warning]
        case when isnull(t1.[Column Name],'') = isnull(t2.[Column Name],'') 
                and (
                     isnull(t1.[Data Type],'') <> isnull(t2.[Data Type],'')
                     or
                     isnull(cast(t1.CHARACTER_MAXIMUM_LENGTH as varchar(50)),isnull(cast(t1.NUMERIC_PRECISION as varchar(50)),'') + ',' +
                            isnull(cast(t1.NUMERIC_SCALE as varchar(50)),''))
                        <> 
                     isnull(cast(t2.CHARACTER_MAXIMUM_LENGTH as varchar(50)),isnull(cast(t2.NUMERIC_PRECISION as varchar(50)),'') + ',' +
                            isnull(cast(t2.NUMERIC_SCALE as varchar(50)),''))
                     )
            then '*** Data Type Mismatch ***' else '' end 
    [Data Type Warning]
from #temp_table1 t1 
    full outer join #temp_table2 t2 on t1.[Column Name] = t2.[Column Name]
where 1=1

drop table #temp_table1, #temp_table2
go

这是示例结果集:

enter image description here