将所有表的数据类型与plsql中的一个配置表进行比较

时间:2018-02-25 11:52:22

标签: sql oracle plsql

我有一个表CONFIG_PRAM,其中包含colnamedatatype等列以及现有表格的更多详细信息。

实施例

CREATE TABLE CONFIG_PRAM 
(   colname varchar(40),  
   datatype varchar(40)  
 );

我必须将CONFIG_PRAM表中的这些列和数据类型与现有表的列进行比较。

示例:我在数据库中有一个现有的表 test1

create table test1 ( employee_id   NUMBER(6),
                     sal    NUMBER(6,8));

如果发现任何不匹配,我需要使用正确的数据类型更新CONFIG_PRAM表。

对于CONFIG_PRAM表中的上述内容我们有sal number 但实际上它在表中是number(6,8)所以我必须使用确切的数据类型更新CONFIG_PRAM表。

我试过这样的话:

select distinct colname , datatype 
from CONFIG_PRAM , all_tab_columns
where upper(column_name)=upper(colname )
and data_type=datatype 
and table_name in ('TEST1') 

但假设表A有Number(6,8) 和CONFIG_PRAM表仅包含Number 那么它没有给出正确的结果。 问题是此查询未完全比较十进制值。能否请您在sql / PLSQL中为此提供解决方案?

2 个答案:

答案 0 :(得分:1)

此查询以COLUMN_NAME为基础将您的表连接到ALL_TAB_COLUMNS。这意味着只有当CONFIG_PRAM只有一个表的条目时它才能正常工作。也许它还需要TABLE_NAME的列?

select cp.colname 
       , cp.datatype as config_datatype
       , atc.data_type as actual_datatype
       , atc.data_length as actual_length
       , atc.data_precision as actual_precision
       , atc.data_scale as actual_scale
from CONFIG_PRAM cp
     join all_tab_columns atc
     on atc.column_name = cp.colname
where atc.owner = user 
and atc.table_name in ('TEST1')
and upper(cp.datatype) != case 
       when atc.data_type = 'VARCHAR2' 
            then atc.data_type||'('||atc.data_length||')'
       when atc.data_type = 'NUMBER' 
            and instr(cp.datatype, ',') = 0
            and atc.data_scale = 0 
            then atc.data_type||'('||atc.data_precision||')'
       when atc.data_type = 'NUMBER' 
            then atc.data_type||'('||atc.data_precision||','||atc.data_scale||')'
       else atc.data_type
       end 
;

WHERE子句将datatype列与汇编的数据类型字符串进行比较。显然,有比此查询处理更多的潜在数据类型。您需要根据需要进行扩展。此外,数据类型字符串格式的变化将产生误报。因此,您应该对CONFIG_PRAM表的结构有一个正确的考虑:您在插入或更新时应用的规则越松散,在选择使用时您需要做的工作就越多。

这是a SQL Fiddle demo

答案 1 :(得分:0)

ALL_TAB_COLUMNS包含的内容比data_type多得多。您还需要至少比较data_lengthdata_precisiondata_scale

您的联接也缺少table_nameowner,最好使用ANSI连接语法。