Oracle -检查表中是否存在列(是/否)

elcex8rz  于 2023-05-28  发布在  Oracle
关注(0)|答案(2)|浏览(392)

我正在尝试编写一个Oracle查询,它接受表的多个列,并为每一列返回行,并带有一个标志,即输入列是否存在?
表DDL -

CREATE TABLE orders
    ( 
       id           NUMBER(10),
      order_mode     VARCHAR2(8),
      cust_id        NUMBER(6),
      status       NUMBER(2)
   )

为了找出表中存在的列,我执行下面的查询。但它失败并显示错误消息“SQL Error [936][42000]:ORA-00936:缺少表达式“fail”。

SELECT column_name,
       exists (
          SELECT 1
          FROM all_tab_columns
          WHERE table_name = 'ORDERS'
          AND column_name IN ('ORDER_MODE', 'CUST_ID', 'ABC')
       ) AS exists_one_zero
FROM dual;

下面的查询也会失败,并显示“SQL错误[904] [42000]:ORA-00904:色谱柱名称:无效标识符”。

SELECT column_name,
       CASE WHEN exists (
          SELECT 1
          FROM all_tab_columns
          WHERE table_name = 'ORDERS'
          AND column_name IN ('ORDER_MODE', 'CUST_ID', 'ABC')
       ) THEN 'Yes' ELSE 'No' END AS exists_yes_no
FROM dual;

请问上面的问题是什么?

up9lanfz

up9lanfz1#

第一个查询失败,因为Oracle不允许在select子句中使用exists这样的 predicate ;一些数据库会将其转换为布尔值,但在Oracle中,您需要将 predicate Package 在case表达式中(尽管在23 c中也可以工作)。
在第二个查询中,问题是column_name没有在外部的select中定义,即from dual(只有内部的select可以看到该列)。
总的来说,我建议更改逻辑以生成一个固定的列列表作为行,然后使用exists检查它们在all_tab_columns中的存在:

select c.column_name, 
    case when exists (
        select 1
        from all_tab_columns t
        where t.table_name = 'ORDERS' and t.column_name = c.column_name
    ) then 'YES' else 'NO' end exists_yes_no
from (
    select 'ORDER_MODE' as column_name from dual
    union all select 'CUST_ID'         from dual
    union all select 'ABC'             from dual
) c

你可以更进一步,把表名也设为一个变量,这样你就可以在所有表中执行相同的检查:

select c.column_name, 
    case when exists (
        select 1
        from all_tab_columns t
        where t.table_name = c.table_name and t.column_name = c.column_name
    ) then 'YES' else 'NO' end exists_yes_no
from (
    select 'ORDERS' table_name, 'ORDER_MODE' as column_name from dual
    union all select 'CUSTOMERS', 'CUST_ID' from dual
) c

旁注:我建议将列OWNER添加到ALL_TAB_COLUMNS查找的WHERE子句中,因为不同的表在不同的模式中可能具有相同的名称。或者考虑查询USER_TAB_COLUMNS,它只允许您访问自己的模式。

q1qsirdb

q1qsirdb2#

你不需要使用EXISTS。相反,您可以左连接两个查询-一个定义要针对表进行测试的列名列表,另一个从all_tab_columns获取表的列名。使用Case表达式检查是否存在

Select  
    l.COLUMN_NAME, 
    CASE WHEN c.COLUMN_NAME Is Null THEN 'NO' ELSE 'YES' END "EXISTS"  

From      
    (   Select 'ORDER_MODE' "COLUMN_NAME" From Dual Union All
        Select 'CUST_ID'     From Dual Union All
        Select 'SOME_COL'    From Dual  ) l

Left Join    
    ( Select COLUMN_NAME 
      From all_tab_columns 
      Where TABLE_NAME = 'ORDERS' And
            OWNER = 'TAB_OWNER_NAME') c ON(c.COLUMN_NAME = l.COLUMN_NAME)

--  
--  R e s u l t :       
--  COLUMN_NAME EXISTS
--  ----------- ------
--  ORDER_MODE  YES
--  CUST_ID     YES
--  SOME_COL    NO

相关问题