1

我尝试从多列(数据类型编号)中搜索一个数字,但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');

它有什么问题?

4

2 回答 2

1

您的查询是:

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'

该子查询将返回列名列表,例如

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 来实现您的目标。

于 2015-08-24T16:29:04.820 回答
1

您将数字 1481125 与每一列的名称进行比较,而不是表中每一列的值。

要从列名(从 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;
于 2015-08-24T17:56:40.580 回答