从具有数字数据类型的多列中查询特定整数值

Query for particular integer value from multiple columns with number datatype

我尝试从多列(数据类型数字)中搜索数字,但出现 ORA-01722: invalid number 错误。

我的查询:

SELECT *
 FROM CAMPAIGN
WHERE 1481125 IN (select column_name
                    from all_tab_columns
                   where table_name = 'CAMPAIGN'
                     AND data_type = 'NUMBER');

有什么问题吗?

您的查询是:

SELECT * FROM CAMPAIGN WHERE 1481125 IN 
(select column_name from all_tab_columns where table_name = 'CAMPAIGN' AND data_type='NUMBER')

分解我们有:

SELECT * FROM CAMPAIGN WHERE 1481125 IN (<a set of numbers>)

和子查询:

select column_name from all_tab_columns
where table_name = 'CAMPAIGN' 
AND data_type='NUMBER'

该子查询将 return 列名列表,例如

CAMPAIGN_COUNT
CAMPAIGN_ID
CAMPAIGN_NUMBER_OF_SOMETHINGS

您的查询因此等同于:

SELECT * FROM CAMPAIGN WHERE 1481125 IN 
   ('CAMPAIGN_COUNT', 'CAMPAIGN_ID', 'CAMPAIGN_NUMBER_OF_SOMETHINGS')

您可以看到为什么会出现 ORA-01722 错误吗?

您需要编写动态 SQL 来实现您的目标。

您正在将数字 1481125 与每一列的名称进行比较,而不是 table.

中每一列的值

要从列名(从 dba_tab_columns)到该列中的值,您需要使用某种形式的动态 SQL。这是一个相对简单的例子:

DECLARE
  -- Since I don't have your CAMPAIGN table or data, I'm using DBA_OBJECTS in it's place.
  l_table_name      VARCHAR2 (30) := 'DBA_OBJECTS';
  l_search_number   NUMBER := 20;                                                             -- 1481125 in your example
  l_record          dba_objects%ROWTYPE;
  l_sql             VARCHAR2 (32000);
  l_column_number   NUMBER := 0;
  l_cur             SYS_REFCURSOR;
BEGIN
  -- First: build dynamic SQL statement of the form:
  -- SELECT * FROM table_name WHERE
  -- ( ( col_name_a = 20 ) OR ( col_name_b = 20 ) OR ... )
  l_sql   := 'SELECT * FROM dba_objects WHERE ( ';

  FOR r_number_column IN (SELECT column_name
                          FROM   dba_tab_columns
                          WHERE  table_name = l_table_name
                          AND    data_type = 'NUMBER'
                          ORDER BY column_id) LOOP
    IF l_column_number > 0 THEN
      l_sql   := l_sql || ' OR ';
    END IF;

    l_column_number   := l_column_number + 1;
    l_sql             := l_sql || '(' || r_number_column.column_name || ' = ' || l_search_number || ')';
  END LOOP;

  IF l_column_number = 0 THEN
    -- No number columns in table, so there should be no matches
    l_sql   := l_sql || ' 1=0';
  END IF;

  l_sql   := l_sql || ')';

  DBMS_OUTPUT.put_line (l_sql);

  OPEN l_cur FOR l_sql;

  LOOP
    FETCH l_cur INTO   l_record;

    EXIT WHEN l_cur%NOTFOUND;
    DBMS_OUTPUT.put_line ('Object Name ' || l_record.object_name || ' has search number ' || l_search_number);
  END LOOP;
END;