繁体   English   中英

比较oracle中两个表列的数据类型

[英]compare data types of two table columns in oracle

考虑我有2个数据库A1和A2,它们都有相似的表,考虑A1中的T1和A2中的T2。

我需要一个sql查询来比较表中每一列的数据类型,该查询应返回与两个表中的数据类型都不匹配的列名。

这种类型的问题有一个非常漂亮且非常有效的解决方案-没有联接,没有MINUS操作等,并且仅通过ALL_TAB_COLUMNS可能是一个很大的表。 它是由Marco Stefanelli(如果我没记错的话)最早在几年前在AskTom上提出的,在此进行了改进,并已成为表比较的标准。

我没有两个不同的数据库可玩,所以我仅说明如何比较不同模式中的表。 您将需要适应您的情况(您可能必须从两个数据库中的USER_TAB_COLUMNS中读取信息。)

在这种情况下,我们选择表所有者,表名称以及列名称,数据类型和其他特征; 我们使用GROUP BY列名和所有这些列属性; 并且我们仅选择行HAVING COUNT(*) = 1 实际上,如果两张表中的列具有相同的名称和所有相同的特征,则计数将为2,并且输出中将没有对应的行。 仅在以下情况下,输出才会显示一行(对应于一个列名+两个或两个原始表中的属性):列名仅出现在一个表中,而不出现在另一个表中; 或者,如果列名同时出现在两个表中,但至少一个属性不同。 尝试在下面的最终输出中发现差异!

如您所见,在解决方案中,我需要选择max(owner)max(table_name) -因为我不按这些列进行分组-但实际上我只选择了只有一行的组,因此max()确实没有任何作用。

设置:我在自己的“沙盒”(我为自己创建的架构,称为INTRO )中从SCOTT架构复制了EMP表。 我使用CTAS创建副本-这将复制所有列名和数据类型(视情况包括大小/精度/小数位数),但是例如,它不会复制“非空”约束。 因此,我包括了ALL_TAB_COLUMNSnullablenullable列,以捕获此类差异。 通过使用“始终为假”的WHERE过滤器,我仅选择表结构,而不选择数据。

create table empl as select * from scott.emp where 0 is null;
Table EMPL created.

alter table empl drop column comm;
Table EMPL altered.

alter table empl add sex char(1);
Table EMPL altered.

alter table empl modify job varchar2(20);
Table EMPL altered.

alter table empl modify deptno not null;
Table EMPL altered.

所以现在我有:

describe scott.emp

Name     Null     Type         
-------- -------- ------------ 
EMPNO    NOT NULL NUMBER(4)    
ENAME             VARCHAR2(10) 
JOB               VARCHAR2(9)  
MGR               NUMBER(4)    
HIREDATE          DATE         
SAL               NUMBER(7,2)  
COMM              NUMBER(7,2)  
DEPTNO            NUMBER(2) 


describe intro.empl

Name     Null     Type         
-------- -------- ------------ 
EMPNO             NUMBER(4)    
ENAME             VARCHAR2(10) 
JOB               VARCHAR2(20) 
MGR               NUMBER(4)    
HIREDATE          DATE         
SAL               NUMBER(7,2)  
DEPTNO   NOT NULL NUMBER(2)    
SEX               CHAR(1)

解决方案 (查询以比较两个表):

select   max(owner) as owner, max(table_name) as table_name,
         column_name, data_type, data_length, data_precision, data_scale, nullable
from     all_tab_columns
where    (owner = 'SCOTT' and table_name = 'EMP')
   or    (owner = 'INTRO' and table_name = 'EMPL')
group by column_name, data_type, data_length, data_precision, data_scale, nullable
having   count(*) = 1
order by column_name, owner, table_name;

输出

OWNER TABLE_NAME COLUMN_NAME DATA_TYPE DATA_LENGTH DATA_PRECISION DATA_SCALE NULLABLE
----- ---------- ----------- --------- ----------- -------------- ---------- --------
SCOTT EMP        COMM        NUMBER             22              7          2        Y
INTRO EMPL       DEPTNO      NUMBER             22              2          0        N
SCOTT EMP        DEPTNO      NUMBER             22              2          0        Y
INTRO EMPL       EMPNO       NUMBER             22              4          0        Y
SCOTT EMP        EMPNO       NUMBER             22              4          0        N
INTRO EMPL       JOB         VARCHAR2           20                                  Y
SCOTT EMP        JOB         VARCHAR2            9                                  Y
INTRO EMPL       SEX         CHAR                1                                  Y

如果需要将一个表与另一个表进行比较,以查找名称相同但类型不同的列,则可以使用以下内容。

设定:

create table t1(a number, b varchar2(16), c date, d clob);
create table t2(a number, b varchar2(99), c timestamp, d clob);

查询:

select db1.column_name, db1.table_name, db2.table_name
from all_tab_columns db1
     inner join all_tab_columns db2
       on (db1.owner = db2.owner
           and db1.column_name = db2.column_name)       
where db1.table_name = 'T1'
  and db2.table_name = 'T2'
  and (
           db1.data_type != db2.data_type
        OR db1.data_length != db2.data_length
      ) 

COLUMN_NAME                    TABLE_NAME                     TABLE_NAME
-------------------------- -------------------------- --------------------------
B                          T1                         T2
C                          T1                         T2

这将检查同一数据库上的表; 要在两个数据库之间使用它,您应该具有从一个实例到另一个实例的dblink,并用all_tab_columns@yourDBLink替换一次出现的all_tab_columns

请注意,这仅考虑两个表上存在的名称相同但类型不同的列; 这将无法处理名称不同的列或仅存在于一个表中的列的情况

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM