Sql VARCHAR最大长度为4000,但只能存储2666字节长的泰国文本

Sql VARCHAR最大长度为4000,但只能存储2666字节长的泰国文本,sql,oracle,oracle11g,Sql,Oracle,Oracle11g,我正在使用Oracle database 11g和PL/SQL。程序是用C#,.NET4编写的 我有一个带有varchar(4000)列的表,我想在DB中存储泰语文本。 我发现,当我试图用泰语存储文本时,其长度超过1333,Oracle抛出了一个异常,尽管最大长度为4000: ORA-01461:只能为插入到长列中绑定长值 我还注意到,当我使用较小的限制时,它会按预期工作。i、 e.:varchar(10)-允许长度为10或更长的值引发异常: ORA-01401插入值对于列来说太大 根据我已经做

我正在使用Oracle database 11g和PL/SQL。程序是用C#,.NET4编写的

我有一个带有varchar(4000)列的表,我想在DB中存储泰语文本。 我发现,当我试图用泰语存储文本时,其长度超过1333,Oracle抛出了一个异常,尽管最大长度为4000:

ORA-01461:只能为插入到长列中绑定长值

我还注意到,当我使用较小的限制时,它会按预期工作。i、 e.:varchar(10)-允许长度为10或更长的值引发异常:

ORA-01401插入值对于列来说太大

根据我已经做的测试,我可以假设从一个数字“X”开始,oracle停止计算实际字母的长度。相反,它将最长字母长度值中的字母数相乘(在泰语中,最长字母的长度为3,这意味着它类似于3个字符),因此1333*3=3999,我只能再添加一个字符(在类似英语的语言中)

我的问题是:

  • 为什么对于不同的最大长度,行为会有所不同
  • 在我尝试将文本插入表格之前,我可以知道文本的真正限制吗?(假设文本为泰语和英语,也可能为不同语言)
  • 重要提示:因为我需要支持一个非常大且运行正常的系统,所以我无法将数据类型切换到club,但这会解决问题

    谢谢你的帮助


    编辑

    我计算了1333个字符的字节数。它们的字节长度是2666,仍然小于4000。我知道最大长度是以字节为单位的,但我不明白为什么会出现上述异常。 我使用:
    System.Text.ascienceoding.Unicode.GetByteCount(Text)
    检查字节数。

    问题 描述VARCHAR时,应提供一个单位,例如
    VARCHAR2(200字节)
    VARCHAR2(200字符)
    。如果省略该单元,默认值为
    字节
    (请参阅Oracle数据库概念,第章)。这看起来像是一个次要的细节,但当您有多字节字符集时,它会变得非常严重

    高达11克的情况 不幸的是,VARCHAR2列的最大大小有一个硬限制。它是4000字节(!)(请参阅Oracle数据库参考,第章)到Oracle 11g和。这是一个硬限制,没有办法绕过。解决这个问题的唯一方法是使用CLOB列

    12c溶液 Oracle 12c上的情况有所不同。在那里,您可以使用参数
    MAX\u STRING\u SIZE=EXTENDED
    将限制提高到32767字节(请参阅《Oracle数据库语言参考》一章和《Oracle数据库参考》一章)。因此,显而易见的解决方案是:升级到Oracle 12c,设置
    MAX\u STRING\u SIZE=EXTENDED
    并更改表定义。在更改表时,可能会丢失一些索引,因为在12c之前,not索引不能保存超过4000字节的VARCHAR2值,并且可能还有一些限制。(我必须检查索引的问题,以及是否可以通过重建索引来修复)

    解决方案:更改数据库编码 您可以尝试更改本机数据库编码(数据库将字符映射为字节的方式)。为此,通常必须创建一个新数据库,并为NLS_CHARACTERSET提供适当的参数。这是数据库运行方式的一个非常大的变化,可能会产生一些副作用。如果您尝试以不同的编码添加字符,则可能是运气不佳(即无法将它们存储在数据库中)。所以我不建议这个解决方案

    解决方案:切换到CLOB 通常不需要在这样大的文本字段上提供任意查询。您可以尝试识别在大文本列上选择的查询,并将它们迁移到CLOB列上。但这是一个非常大的变化,可能不可能与您现有的模式或您的应用程序。最后可能会出现一堆“而不是”触发器,并缺少一些约束检查(涉及新创建的CLOB列)

    解决方案:使用XML
    您可以尝试将字符串存储为XML列,而不是CLOB。这些设备的最大容量为4GB。这将影响您的性能,您将不得不提供而不是触发器,并且您可能会失去一些约束,但它可能对您有效

    4000
    表示4000字节而不是字符。如果使用多字节字符集,则字符最多可由4个字节组成(取决于字符集),使用
    varchar
    列无法克服此限制。如果需要更多,则需要使用
    CLOB
    column数据库的NLS\U字符集设置为什么?您考虑过
    nvarhar2
    列吗?@Wooble:a
    nvarhar2
    列也被限制为4000字节。数据库中存储的1333个字母的字节为2668字节,小于4000字节。另外,nvarchar也有同样的问题。@hadaco:用什么编码?UTF-8对所有泰语字符使用3个字节。请注意,在Oracle 12c中,VARCHAR2的限制已提高到32767个字节。谢谢!我相应地更改了答案。做得很好,但不确定您的语句“索引不能保存超过4000字节的VARCHAR2值”-我非常确定它们可以,否则12c将被视为已损坏。只是有些函数索引可能无法使用,但可以修复。好的,我必须检查关于12c上索引的语句。大(>4000字节)列上的索引工作正常。根据文档,功能索引可能会出现问题,您将无法获得工作索引。但我无法重现这个问题。