Получить только имена столбцов без выполнения SQL-запроса на plsql? - PullRequest
0 голосов
/ 19 октября 2018

Я получил ORA-00918: столбец двусмысленно определен ошибка

Мне нужно обрабатывать имена столбцов без выполнения всех длинных запросов.Поэтому я пытаюсь свернуть основной запрос с помощью

`select * from (--main query--) Where 1=2`

и обработать результат emtpy, успех!

Но есть проблема с некоторыми запросами:

SELECT * => ORA-00918: column ambiguously defined
  FROM (SELECT A.*, A.ASSOCIATION_NO
          FROM CUSTOMER_INFO A
         WHERE A.ASSOCIATION_NO IS NOT NULL)
 WHERE 1 = 2

Как можно решить это?

Ответы [ 3 ]

0 голосов
/ 21 октября 2018

Вы можете использовать DBMS_SQL для получения имен столбцов.Сначала необходимо проанализировать запрос, а затем использовать одну из процедур description_columns, чтобы получить информацию о столбцах, которая включает имена.Это на самом деле не выполняет запрос.

Я не уверен, что шаг разбора будет выполнен успешно, так как, как отмечалось выше, я думаю, что ваш запрос технически недействителен.Тебе повезло, что в данный момент он работает.

0 голосов
/ 22 октября 2018

Получая комментарии togetehr, вы можете использовать dbms_sql для анализа (но не выполнения) целевого запроса и описания столбцов набора результатов для получения необходимой информации.

Из этих документов :

Каждый оператор SQL должен быть проанализирован путем вызова процедур PARSE.Разбор оператора проверяет синтаксис оператора и связывает его с курсором в вашей программе.

Вы можете анализировать любой оператор DML или DDL.Операторы DDL выполняются при синтаксическом анализе, который выполняет подразумеваемую фиксацию.

, поскольку, поскольку оператор является просто DML, а не DDL, он будет только анализироваться и не выполняться, посколькувы не продолжите выполнение.

С фиктивной таблицей для демонстрации:

create table customer_info (association_no number(10),
  col_vc varchar2(20), col_d date, col_n number(2,5), col_ts timestamp(3));

тогда базовая версия будет иметь вид:

declare
  -- your target query, could be a pprocedure argument etc.
  l_statement varchar2(4000) := 'SELECT A.*, A.ASSOCIATION_NO
          FROM CUSTOMER_INFO A
         WHERE A.ASSOCIATION_NO IS NOT NULL';
  -- variabels dbms_sql use
  l_c pls_integer;
  l_col_cnt pls_integer;
  l_desc_t dbms_sql.desc_tab4;
  -- local variabels to hold columninfo as required
  l_column_name all_tab_cols.column_name%type;
  l_data_type varchar2(20);
begin
  l_c := dbms_sql.open_cursor;
  dbms_sql.parse(c=>l_c, statement=>l_statement, language_flag=>dbms_sql.native);
  dbms_sql.describe_columns3(c=>l_c, col_cnt=>l_col_cnt, desc_t=>l_desc_t);

  for i in 1..l_col_cnt loop
    l_column_name := l_desc_t(i).col_name;
    l_data_type := case l_desc_t(i).col_type
        when 1 then 'VARCHAR2'
        when 2 then 'NUMBER'
        when 12 then 'DATE'
        when 96 then 'CHAR'
        when 180 then 'TIMESTAMP'
        -- more types as needed
        ELSE 'unknown'
      end;
    case
      when l_desc_t(i).col_type in (1, 96) then -- or nchar etc. if needed
        l_data_type := l_data_type || '(' || l_desc_t(i).col_max_len || ')';
      when l_desc_t(i).col_type = 2 then
        l_data_type := l_data_type || '(' || l_desc_t(i).col_precision
          || ',' || l_desc_t(i).col_scale || ')';
      when l_desc_t(i).col_type = 180 then
        l_data_type := l_data_type || '(' || l_desc_t(i).col_scale || ')';
      else
        null;
    end case;

    -- use for insert, or just to debug for now
    dbms_output.put_line(l_column_name || ' ' || l_data_type);
  end loop;

  dbms_sql.close_cursor(l_c);
exception
  when others then
    if (dbms_sql.is_open(l_c)) then
      dbms_sql.close_cursor(l_c);
    end if;
    raise;
end;
/

, котораядает вывод:

ASSOCIATION_NO NUMBER(10,0)
COL_VC VARCHAR2(20)
COL_D DATE
COL_N NUMBER(2,5)
COL_TS TIMESTAMP(3)
ASSOCIATION_NO NUMBER(10,0)


PL/SQL procedure successfully completed.

Если вы ожидаете другие типы данных, включите подходящую обработку для них тоже.Типы данных и эквивалентные числа перечислены в документации .

Между прочим, я связался с документами 12c и протестировал против 12cR2, поэтому я использовал новейшую структуру desc_tab4 и describe_columns3 функция.Используйте самую последнюю версию структуры / вызова, доступную для версии Oracle, против которой вы разрабатываете;если вы используете 11gR2, тогда desc_tab3, например.Структура имеет col_type_name, но, похоже, она не заполнена даже в 12cR2.У меня нет 18с для проверки.

0 голосов
/ 19 октября 2018

Укажите псевдоним для столбца, так как ASSOCIATION_NO упоминается дважды.

Это не будет проблемой, если вы используете один запрос ... но запрос записывается как подзапрос, проблема возникает ..

SELECT 
    A.*, A.ASSOCIATION_NO
FROM 
    CUSTOMER_INFO A
WHERE 
    A.ASSOCIATION_NO IS NOT NULL

Это будет работать без каких-либо проблем, но когда вы вводите это как подзапрос, система выдает эту ошибку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...