【问题标题】:Compare two tables and find the missing column using left join比较两个表并使用左连接查找缺失的列
【发布时间】:2022-09-27 17:26:31
【问题描述】:

我想比较两个表employees 和employees_a 并找到表comployees_a 中缺少的列。

 select a.Column_name,
From User_tab_columns a
LEFT JOIN User_tab_columns b
   ON upper(a.table_name) = upper(b.table_name)||\'_A\'
  AND a.column_name = b.column_name
Where upper(a.Table_name) = \'EMPLOYEES\'
AND upper(b.table_name) = \'EMPLOYEES_A\'
AND b.column_name is NULL
;

但这似乎不起作用。不返回任何行。

我的员工表有以下列

  1. emp_name
  2. emp_id
  3. base_location
  4. 部门
  5. 当前位置
  6. 工资
  7. 经理

    employees_a 表具有以下列

    1. emp_name
    2. emp_id
    3. base_location
    4. 部门
    5. 当前位置

      我想找到剩下的两列并将它们添加到 employees_a 表中。

      我有 50 多个这样的表来比较它们并找到丢失的列并将这些列添加到它们各自的 \"_a\" 表中。

    标签: select oracle12c alter-table


    【解决方案1】:

    缺少列?为什么不使用 MINUS 集合运算符,似乎更简单,例如

    select column_name from user_tables where table_name = 'EMP_1'
    minus
    select column_name from user_tables where table_name = 'EMP_2'
    

    【讨论】:

    • 试过了,但我有 50 多个这样的例子。离开和离开_a。所以我需要比较所有有像_a这样的重复表的表。所以这没有用
    【解决方案2】:

    口渴,检查 user_tab_columns 表是否包含表的列(在我的情况下 user_tab_columns 是空的,我必须使用 all_tab_columns):

    select a.Column_name
    From User_tab_columns a
    Where upper(a.Table_name) = 'EMPLOYEES'
    

    其次,删除线AND 上(b.table_name)='EMPLOYEES_A',因为在未找到列的情况下,upper(b.table_name) 为空。您已经在 SELECT 的 JOIN 部分中有 b.table_name 。

    select a.Column_name
    From User_tab_columns a
    LEFT JOIN User_tab_columns b
       ON upper(a.table_name) = upper(b.table_name)||'_A'
      AND a.column_name = b.column_name
    Where upper(a.Table_name) = 'EMPLOYEES'
    AND b.column_name is NULL
    

    【讨论】:

      【解决方案3】:

      您不需要任何连接,可以使用:

      select 'ALTER TABLE EMPLOYEES_A ADD "'
               || Column_name || '" '
               || CASE MAX(data_type)
                  WHEN 'NUMBER'
                  THEN 'NUMBER(' || MAX(data_precision) || ',' || MAX(data_scale) || ')'
                  WHEN 'VARCHAR2'
                  THEN 'VARCHAR2(' || MAX(data_length) || ')'
                  END
               AS sql
      From   User_tab_columns
      Where  Table_name IN ('EMPLOYEES', 'EMPLOYEES_A')
      GROUP BY COLUMN_NAME
      HAVING COUNT(CASE table_name WHEN 'EMPLOYEES'   THEN 1 END) = 1
      AND    COUNT(CASE table_name WHEN 'EMPLOYEES_A' THEN 1 END) = 0;
      

      或者,对于多个表:

      select 'ALTER TABLE ' || MAX(table_name) || '_A ADD "'
               || Column_name || '" '
               || CASE MAX(data_type)
                  WHEN 'NUMBER'
                  THEN 'NUMBER(' || MAX(data_precision) || ',' || MAX(data_scale) || ')'
                  WHEN 'VARCHAR2'
                  THEN 'VARCHAR2(' || MAX(data_length) || ')'
                  END
               AS sql
      From   User_tab_columns
      Where  Table_name IN ('EMPLOYEES', 'EMPLOYEES_A', 'SOMETHING', 'SOMETHING_A')
      GROUP BY
             CASE
             WHEN table_name LIKE '%_A'
             THEN SUBSTR(table_name, 1, LENGTH(table_name) - 2)
             ELSE table_name
             END,
             COLUMN_NAME
      HAVING COUNT(CASE WHEN table_name NOT LIKE '%_A' THEN 1 END) = 1
      AND    COUNT(CASE WHEN table_name LIKE '%_A'     THEN 1 END) = 0;
      

      fiddle

      【讨论】:

      • 嗨,谢谢你的回答。多表答案非常有帮助。但是对于 where 子句中的所有 50 个 table_names 来说很难。但我所有的表都以emp开头。因此,如果我使用 like 'emp%',那么它会从所有其他也以 emp 开头的表中选择所有列名。我只需要从具有_a 的那些中进行选择。
      • @DataGeek 只需在 IN 子句中写出 50 个表名,然后复制粘贴并将 _A 附加到它们。你可能会做一些自动化的事情,但只需要 1 到 2 分钟的打字来解决它,所以花费 10 分钟自动化它几乎没有意义。
      猜你喜欢
      • 2021-12-23
      • 2019-08-04
      • 1970-01-01
      • 1970-01-01
      • 2017-08-28
      • 2011-12-21
      • 1970-01-01
      • 1970-01-01
      • 2015-10-18
      相关资源
      最近更新 更多