【问题标题】:SQL Server: compare columns in two tablesSQL Server:比较两个表中的列
【发布时间】:2020-06-21 15:43:55
【问题描述】:

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

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

【问题讨论】:

  • 您只想比较列或列和约束的哪些 db 对象?真的,这是一个大脚本。 :) 你用的是什么版本的sql server?
  • 为了简单起见,让我们忘记约束,我使用的是 SQL Server 2005。是的,这是一个巨大的脚本。

标签: sql sql-server database


【解决方案1】:

看看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

【讨论】:

  • 不错!非常感谢。我还在存储过程 sp_columns 中找到了一个构建,它需要表名作为参数。
【解决方案2】:

我真的建议您使用第三方比较工具,例如上面已经提到的 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'

【讨论】:

    【解决方案3】:

    这对我有用(遇到了同样的问题,刚刚编译了我的解决方案)

    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 设置值并运行脚本;)

    【讨论】:

    • 这个是最简单的,直接插入一些表名而不做修改。请注意,您可能希望增加表名的 30 字符限制。我的表名很长,在我修复之前没有得到任何结果。
    【解决方案4】:

    确实这是一个大脚本。 :)

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

    如果你真的需要脚本,它可以是一个文本,然后你可以使用任何文本比较器来比较两者。

    【讨论】:

    • @igor 是对的,不要自己写这个,有很多应用程序可以做到这一点。 Apex SQL Diff 是另一个免费试用版。
    【解决方案5】:

    我发现 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
    

    这是一个示例结果集:

    【讨论】:

      猜你喜欢
      • 2012-08-01
      • 1970-01-01
      • 2017-11-01
      • 1970-01-01
      • 2021-04-24
      • 1970-01-01
      • 2010-11-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多