当前位置: 首页 > 知识库问答 >
问题:

Oracle:强制VARCHAR2和CLOB为相同类型而不截断

长孙绍辉
2023-03-14

在支持MS SQL Server、MySQL和Oracle的应用程序中,有一个包含以下相关列的表(此处显示的类型是Oracle的类型):

ShortText VARCHAR2(1700) indexed
LongText CLOB

该应用商店的短文本值为850个或更少的字符,长文本值为更长的字符。我需要创建一个视图来返回数据,无论数据在哪个列。这适用于SQL Server和MySQL:

SELECT
  CASE
    WHEN ShortText IS NOT NULL THEN ShortText
    ELSE LongText
  END AS TheValue
FROM MyTable

但是,在Oracle上,它会生成以下错误:

ORA-00932: inconsistent datatypes: expected CHAR got CLOB 

...这意味着Oracle不会隐式地将这两个列转换为相同的类型,因此查询必须显式地进行转换。不希望数据被截断,所以使用的类型必须能够容纳与CLOB一样多的数据,根据我的理解(不是Oracle专家)意味着CLOB,只是,没有其他选择可用。

这适用于Oracle:

SELECT
  CASE
    WHEN ShortText IS NOT NULL THEN TO_CLOB(ShortText)
    ELSE LongText
  END AS TheValue
FROM MyTable

所以:

  1. 是否还有其他Oracle类型可以强制将两列都设置为可以容纳与CLOB一样多的数据?理想的方法是更面向文本的,比如MySQL的LONGTEXT或SQL Server的NTEXT(或者更好的方法是NVARCHAR(MAX))?
  2. 我还应该考虑其他方法吗?

一些细节,尤其是@Guido Leenders要求的细节:

Oracle version: Oracle Database 11g 11.2.0.1.0 64bit Production
Not certain if I was the only user, but the relative times are still striking.

Stats for the small table where I saw the performance I posted earlier:
  rowcount: 9,237
  varchar column total length: 148,516
  clob column total length: 227,020

共有1个答案

邵崇凛
2023-03-14

to_clob非常昂贵,所以尽量避免使用它。但我认为它应该在9K行的情况下表现得相当好。以下测试用例基于我们开发的一个具有类似datamodel行为的应用程序:

create table bubs_projecten_sample
( id number
, toelichting varchar2(1700)
, toelichting_l clob
)

begin
  for i in 1..10000
  loop
    insert into bubs_projecten_sample
    ( id
    , toelichting
    , toelichting_l
    )
    values
    ( i
    , case when mod(i, 2) = 0 then 'short' else null end
    , case when mod(i, 2) = 0 then rpad('long', i, '*') else null end
    )
    ;
  end loop;
  commit;
end;

现在确保缓存和脏块中的所有内容都写出来:

select *
from   bubs_projecten_sample

测试性能:

create table bubs_projecten_flat
as
select id
,      to_clob(toelichting) toelichting_any
from   bubs_projecten_sample
where  toelichting is not null
union all
select id
,      toelichting_l
from   bubs_projecten_sample
where  toelichting_l is not null

作为旁注;我看到850和1700之间的区别。我建议使它们相等,但请记住检查是否使用字符语义创建表。这可以通过使用:“varchar2(850char)”在语句级别上完成。请注意,Oracle实际上将创建一个适合850*4字节的列(至少在AL32UTF8中,其中“32”代表“每个字符最多4字节”)。祝你好运!

 类似资料:
  • 我有一个Oracle表,其中列类型为CLOB。我想保留列顺序并将数据类型更改为VARCHAR2。该列只包含文本。 我得到了一个标准的信息: 我们将不胜感激。我已经在这方面工作了一段时间了。如果你有任何问题请告诉我。

  • 主要内容:Oracle VARCHAR2数据类型简介,Oracle VARCHAR2最大长度,Oracle VARCHAR2的例子在本教程中将学习Oracle 数据类型以及如何使用它来定义可变长度的字符串列。 Oracle VARCHAR2数据类型简介 要存储可变长度的字符串,可以使用Oracle 数据类型。 列可以存储到字节的值。 这意味着对于单字节字符集,最多可以在列中存储个字符。 当使用列创建表时,必须指定最大字符串长度(以字节为单位): 或以字符 - 默认情况下,如果没有在之后显式指定或

  • 我甚至尝试过直接分配 得到同样的结果。 编辑

  • 我们使用的是Oracle,我们有一个要求,允许希腊字符存储在数据库中。目前,我们的DB实例不允许我们插入希腊字符,如“?”。在谷歌上,我发现这与字符集有关。我的oracle使用不支持希腊字符的nls_characterset-we8mswin1252。如果必须工作,我必须将字符集更改为AL32UTF8、UTF8、AL16UTF16或WE8ISO8859P7之一。既然数据库中已经有了这么多的数据,现

  • 问题内容: 我在寻找什么: 我正在寻找一种可以在地图的键和值上强制类型的东西:有点像。但是,我还想 在 每个键/值条目中强制类型匹配,但是 在 条目 之间 ,不必强制任何类型。 例如,在同一张地图中,这些键/值对应视为有效: 映射到 映射到 映射到 但是,这样的事情将是无效的: 映射到 映射到 如何使用Java泛型完成此任务? 我不想要的是: 我知道我可以实现类似的东西,其中对接受相同类型的键/值

  • 问题内容: 表:客户 我想将列从更改为`VARCHAR2(1000) 我尝试也 还 如果数据类型不是Clob,但通常会正常工作,但由于我使用的是oracle toad / apex,所以我得到了。 问题答案: 您可以尝试以下方法: 添加一个新列作为varchar2 将UPDATE CLOB名称更新为varchar2列; 经过 测试数据 : DROP CLOB列 将varchar2列重命名为CLOB