如何在案例选择查询中选择LONG列

时间:2019-01-08 13:14:03

标签: sql oracle

我有一个表,该表的数据类型为LONG。如果编写基本查询以获取该LONG colmun的值,则将得到正确的结果。 例如:

select long_text from fnd_documents_long_text;

这将返回正确的值。

但是,如果我尝试在LONG列中使用case语句,则会出现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;

能否请您提出建议,如何在Select查询中的case语句中检索LONG列的值。

我真正想要的是,如果datatype_id = 1,则从fnd_documents_short_text表中获取short_text,否则,如果datatype_id为2,则从fnd_documents_long_text表中获取long_text,其中“ long_text”的数据类型为LONG。这些是标准的Oracle APPs表。我正在按照以下方式编写查询。.但无法正常工作:

 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 :(得分:2)

restrictions on the LONG data type有很多,这会限制您的选择。

作为您方案的一种可能的解决方法,您可以创建一个函数,将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;

或使用左外部联接到'short'表,而不使用子查询:

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;

答案 1 :(得分:1)

按照建议的here,您可以使用全局临时表

首先将表的相关部分(记录)插入临时表中。比您可以根据需要从中进行选择,因为临时表中的两列都具有相同的类型-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 

答案 2 :(得分:0)

为什么不只做Join?

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;

如果要使用案例/联合查询,可以执行以下操作:

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 ;