Как выбрать длинный столбец в случае выбора запроса - PullRequest
0 голосов
/ 08 января 2019

У меня есть таблица, в которой есть столбец типа LONG. Если я напишу базовый запрос, чтобы получить значение этого длинного colmun, я получу правильные результаты. Например:

select long_text from fnd_documents_long_text;

Возвращает правильное значение.

Но если я попытаюсь использовать оператор case со столбцом LONG, он выдаст ORA-00997: Недопустимое использование ошибки типа данных LONG. Я пытаюсь написать следующий запрос:

 select case when datatype_id = 2 then 
 ( select long_text from fnd_documents_long_text where  media_id= fd.media_id)    end Text
 from fnd_documents fd where document_id = 715193;

Подскажите, пожалуйста, как мне получить значение столбца LONG внутри оператора case в запросе Select.

Что мне действительно нужно, так это то, что если datatype_id = 1, тогда получите short_text из таблицы fnd_documents_short_text, иначе, если datatype_id равен 2, тогда получите long_text из таблицы fnd_documents_long_text, где "long_text" имеет тип данных LONG. Это стандартные таблицы приложений Oracle. Я пишу свой запрос, как показано ниже ... но он не работает нормально:

 select case when datatype_id = 1 then ( select short_text from fnd_documents_short_text where  media_id =fd.media_id)
             when datatype_id = 2 then ( select long_text from fnd_documents_long_text where  media_id =fd.media_id) 
        end Text
   from fnd_documents fd where document_id = 715193 ;

Спасибо, Абх

Ответы [ 3 ]

0 голосов
/ 08 января 2019

В соответствии с предложением здесь вы можете обойти, используя глобальную временную таблицу

Сначала вставьте соответствующую часть (запись) вашей таблицы во временную таблицу. Затем вы можете выбрать его по необходимости, поскольку оба столбца во временной таблице имеют одинаковый тип - CLOB.

Вам не нужно удалять из темп. таблица, COMMIT сделает это.

Пример

create table tab
(short_text varchar2(10),
 long_text LONG,
 datatype_id number);

insert into tab values ('xxx','xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 1);     
insert into tab values ('yyy','yyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 2); 

Это не удалось:

select datatype_id,
case when datatype_id=1 then long_text
else   short_text    end as txt from tab;

ORA-00932: inconsistent datatypes: expected LONG got CHAR

Но копирование данных во временную таблицу работает

CREATE GLOBAL TEMPORARY TABLE t2
(short_text CLOB,
 long_text CLOB,
 datatype_id number)
ON COMMIT DELETE ROWS;

insert into t2 (short_text,   LONG_TEXT, datatype_id )
select short_text,  to_lob(LONG_TEXT), datatype_id from tab; 

select datatype_id,
case when datatype_id=1 then long_text
else   short_text    end as txt from t2;

DATATYPE_ID TXT                                                                             
----------- --------------------------------------------------------------------------------
          1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx                                                
          2 yyy 
0 голосов
/ 08 января 2019

Существует множество ограничений для типа данных LONG , что ограничивает ваши возможности.

В качестве одного из возможных обходных путей для вашего сценария вы можете создать функцию, которая запрашивает значение LONG в локальной переменной, а затем возвращает его как CLOB, например ::

.
create or replace function get_long_text(
  p_media_id fnd_documents_long_text.media_id%type
)
return clob
as
  l_long long;
begin
  select long_text
  into l_long
  from fnd_documents_long_text
  where media_id = p_media_id;

  return to_clob(l_long);
end;
/

Тогда в вашем выражении case вы можете вызвать эту функцию:

select case
         when datatype_id = 1 then (
           select to_clob(short_text)
           from fnd_documents_short_text
           where media_id = fd.media_id
         )
         when datatype_id = 2 then get_long_text(fd.media_id) 
       end as text
from fnd_documents fd
where document_id = 715193;

или с левым внешним соединением к «короткой» таблице вместо использования подзапроса:

select case
         when datatype_id = 1 then to_clob(fdst.short_text)
         when datatype_id = 2 then get_long_text(fd.media_id)
        end as text
from fnd_documents fd
left join fnd_documents_short_text fdst
on fdst.media_id = fd.media_id
where fd.document_id = 715193;

db <> fiddle demo .

А из Oracle 12c вы даже можете объявить функцию как часть CTE, так что вам не нужен постоянный объект базы данных (хотя вам, вероятно, понадобится, если вы будете делать это часто):

-- start of CTE
with function get_long_text(
    p_media_id fnd_documents_long_text.media_id%type
  )
  return clob
  as
    l_long long;
  begin
    select long_text
    into l_long
    from fnd_documents_long_text
    where media_id = p_media_id;

    return to_clob(l_long);
  end;
-- end of CTE
select case
         when datatype_id = 1 then to_clob(fdst.short_text)
         when datatype_id = 2 then get_long_text(fd.media_id)
        end as text
from fnd_documents fd
left join fnd_documents_short_text fdst
on fdst.media_id = fd.media_id
where fd.document_id = 715193;
0 голосов
/ 08 января 2019

Почему бы просто не присоединиться?

SELECT f_d_l_t.long_text as 'Text'
FROM fnd_documents fd
INNER JOIN 
  fnd_documents_long_text f_d_l_t 
         ON f_d_l_t.media_id= fd.media_id AND fd.datatype_id=2
WHERE 
  document_id = 715193;

Если вы хотите использовать запрос case / join, вы можете сделать это:

SELECT 
     OTher_columns,
     MAX(CASE
         WHEN datatype_id = 1 THEN 
               f_d_s_t.short_text
         WHEN datatype_id = 2 THEN 
               f_d_l_t.long_text
     END )as 'Text'
    FROM fnd_documents fd
    LEFT JOIN 
      fnd_documents_long_text f_d_l_t 
             ON f_d_l_t.media_id= fd.media_id
    LEFT JOIN
     fnd_documents_short_text f_d_s_t 
             ON f_d_s_t.media_id= fd.media_id
    WHERE 
      document_id = 715193
    GROUP BY OTher_columns ;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...