检查表中列的存在(是/否)。

huangapple go评论100阅读模式
英文:

Oracle - Check the presence of columns (yes/no) in a table

问题

I'm sorry, but it seems like you're asking for a code translation, and you've requested not to provide translations for code. If you have any non-code related questions or need assistance with something else, please feel free to ask, and I'll be happy to help.

英文:

I am trying to write an Oracle query that accepts multiple columns of a table and returns rows for each column with a flag whether the input column exists or not?

Table DDL -

  1. CREATE TABLE orders
  2. (
  3. id NUMBER(10),
  4. order_mode VARCHAR2(8),
  5. cust_id NUMBER(6),
  6. status NUMBER(2)
  7. )

To find out which column is present in the table, I execute below query. But it fails with the error message "SQL Error [936][42000]: ORA -00936: missing expression" fail.

  1. SELECT column_name,
  2. exists (
  3. SELECT 1
  4. FROM all_tab_columns
  5. WHERE table_name = 'ORDERS'
  6. AND column_name IN ('ORDER_MODE', 'CUST_ID', 'ABC')
  7. ) AS exists_one_zero
  8. FROM dual;

The below query also fails with "SQL Error [904] [42000]: ORA-00904: COLUMN_NAME: invalid identifier".

  1. SELECT column_name,
  2. CASE WHEN exists (
  3. SELECT 1
  4. FROM all_tab_columns
  5. WHERE table_name = 'ORDERS'
  6. AND column_name IN ('ORDER_MODE', 'CUST_ID', 'ABC')
  7. ) THEN 'Yes' ELSE 'No' END AS exists_yes_no
  8. FROM dual;

May I know what is the problem in above queries ?

答案1

得分: 2

Your first query fails because Oracle does not allow a predicate such as exists in the select clause like that; some databases would turn it into a boolean value, but in Oracle, you need to wrap the predicate in a case expression (it will work in 23c though).

In the second query, the problem is that column_name is not defined in the outer select, which is from dual (only the inner select sees that column).

Overall, I would recommend changing the logic to generate a fixed list of columns as rows, then check their presence in all_tab_columns with exists:

  1. select c.column_name,
  2. case when exists (
  3. select 1
  4. from all_tab_columns t
  5. where t.table_name = 'ORDERS' and t.column_name = c.column_name
  6. ) then 'YES' else 'NO' end exists_yes_no
  7. from (
  8. select 'ORDER_MODE' as column_name from dual
  9. union all select 'CUST_ID' from dual
  10. union all select 'ABC' from dual
  11. ) c

You could take this one step further and make the table name a variable as well, so you could perform the same check across tables:

  1. select c.column_name,
  2. case when exists (
  3. select 1
  4. from all_tab_columns t
  5. where t.table_name = c.table_name and t.column_name = c.column_name
  6. ) then 'YES' else 'NO' end exists_yes_no
  7. from (
  8. select 'ORDERS' table_name, 'ORDER_MODE' as column_name from dual
  9. union all select 'CUSTOMERS', 'CUST_ID' from dual
  10. ) c

Side note: I would recommend adding the column OWNER to the WHERE clause of the ALL_TAB_COLUMNS lookup, since different tables may have the same name in different schemas. Alternatively, consider querying USER_TAB_COLUMNS, which lets you access your schema only.

英文:

Your first query fails because Oracle does not allows a predicate such as exists in the select clause like that; some database would turn it to a boolean value, but in Oracle you need to wrap the predicate in a case expression (it will work in 23c though).

In the second query, the problem is that column_name is not defined in the outer select, which is from dual (only the inner select sees that column).

Overall, I would recommend changing the logic to generate a fixed list of columns as rows, then check their presence in all_tab_columns with exists:

  1. select c.column_name,
  2. case when exists (
  3. select 1
  4. from all_tab_columns t
  5. where t.table_name = 'ORDERS' and t.column_name = c.column_name
  6. ) then 'YES' else 'NO' end exists_yes_no
  7. from (
  8. select 'ORDER_MODE' as column_name from dual
  9. union all select 'CUST_ID' from dual
  10. union all select 'ABC' from dual
  11. ) c

You could took this one step forward and make the table name a variable as well, so you could perform the same check across tables:

  1. select c.column_name,
  2. case when exists (
  3. select 1
  4. from all_tab_columns t
  5. where t.table_name = c.table_name and t.column_name = c.column_name
  6. ) then 'YES' else 'NO' end exists_yes_no
  7. from (
  8. select 'ORDERS' table_name, 'ORDER_MODE' as column_name from dual
  9. union all select 'CUSTOMERS', 'CUST_ID' from dual
  10. ) c

Side note: I would recommend adding column OWNER to the WHERE clause of the ALL_TAB_COLUMNS lookup, since different tables may have the same name in different schemas. Alternatively consider querying USER_TAB_COLUMNS, which lets you access your own schema only.

答案2

得分: 1

你不需要使用 EXISTS。而是可以左连接两个查询 - 一个定义要与表进行列名测试的列名列表,另一个从 all_tab_columns 中获取表的列名。使用 Case 表达式来检查存在性。

  1. Select
  2. l.COLUMN_NAME,
  3. CASE WHEN c.COLUMN_NAME Is Null THEN 'NO' ELSE 'YES' END "EXISTS"
  4. From
  5. ( Select 'ORDER_MODE' "COLUMN_NAME" From Dual Union All
  6. Select 'CUST_ID' From Dual Union All
  7. Select 'SOME_COL' From Dual ) l
  8. Left Join
  9. ( Select COLUMN_NAME
  10. From all_tab_columns
  11. Where TABLE_NAME = 'ORDERS' And
  12. OWNER = 'TAB_OWNER_NAME') c ON(c.COLUMN_NAME = l.COLUMN_NAME)

结果:
COLUMN_NAME EXISTS


ORDER_MODE YES
CUST_ID YES
SOME_COL NO

英文:

You don't need to use EXISTS. Instead you could Left Join two queries - the one that defines your list of column names to be tested against a table and the other fetching column names of your table from all_tab_columns. Check the existance using Case expression

  1. Select
  2. l.COLUMN_NAME,
  3. CASE WHEN c.COLUMN_NAME Is Null THEN 'NO' ELSE 'YES' END "EXISTS"
  4. From
  5. ( Select 'ORDER_MODE' "COLUMN_NAME" From Dual Union All
  6. Select 'CUST_ID' From Dual Union All
  7. Select 'SOME_COL' From Dual ) l
  8. Left Join
  9. ( Select COLUMN_NAME
  10. From all_tab_columns
  11. Where TABLE_NAME = 'ORDERS' And
  12. OWNER = 'TAB_OWNER_NAME') c ON(c.COLUMN_NAME = l.COLUMN_NAME)
  13. --
  14. -- R e s u l t :
  15. -- COLUMN_NAME EXISTS
  16. -- ----------- ------
  17. -- ORDER_MODE YES
  18. -- CUST_ID YES
  19. -- SOME_COL NO

huangapple
  • 本文由 发表于 2023年5月25日 21:36:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76332915.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定