我正在使用带有PL / SQL的Oracle数据库11g。程序是用C#,.NET 4编写的。
我有一个包含varchar(4000)列的表,我想在DB中存储一个泰语文本。 我发现当我尝试以泰语存储文本时,它的长度超过1333,Oracle抛出异常,尽管最大长度为4000:
ORA-01461:只能绑定LONG值才能插入LONG列
我还注意到,当我使用较小的限制时,它按预期工作。即:varchar(10) - 允许长度为10和更长文本的值抛出异常:
ORA-01401 插入的值对于列
来说太大了从我已经做过的测试中,我可以假设从一个数字' X' oracle停止计算实际字母的长度。相反,它乘以最长字母长度值中的字母数(泰语中最长的字母长度为3 - 意味着它就像3个字符)所以1333 * 3 = 3999我只能添加另一个字符(用英语这样的语言。)
我的问题:
重要提示:因为我需要支持一个非常庞大且功能正常的系统,我无法将数据类型切换到俱乐部,但它可以解决问题。
感谢您的帮助。
修改
我计算这1333个字符的字节数。它们的字节长度是2666,仍然是,小于4000.我知道最大长度是以字节为单位,但我不明白为什么我会得到上面的例外。
我使用:System.Text.ASCIIEncoding.Unicode.GetByteCount(text)
来检查字节数。
答案 0 :(得分:6)
在描述VARCHAR时,您应该提供一个单位,例如VARCHAR2(200 BYTE)
或VARCHAR2(200 CHAR)
。如果省略该单元,则默认值为BYTE
(请参阅Oracle数据库概念,第Oracle Datatypes章)。这似乎是一个小细节,但是当你有多字节字符集时会变得非常严重。
不幸的是,VARCHAR2列的最大大小存在硬性限制。它是4000 BYTE(!)(参见Oracle数据库参考,章节Oracle Datatypes),直到Oracle 11g和。这是一个硬限制,没有办法解决这个问题。唯一的解决方法是使用CLOB列。
Oracle 12c的情况有所不同。在那里,您可以使用参数MAX_STRING_SIZE = EXTENDED
将限制提升至32767 BYTE(请参阅Oracle数据库语言参考,章节Data Types和Oracle数据库参考,章节Initialization Parameters)。所以显而易见的解决方案是:升级到Oracle 12c,设置MAX_STRING_SIZE = EXTENDED
according to the documentation并更改表定义。在更改表时可能会丢失一些索引,因为之前到12c而不是索引不能保存具有超过4000个BYTE的VARCHAR2值,并且可能仍然存在一些限制。 (我必须检查索引的问题以及是否可以通过重建索引来修复它。)
您可以尝试更改本机数据库编码(数据库将CHAR映射到BYTE的方式)。为此,您通常必须创建一个新数据库并为NLS_CHARACTERSET提供适当的参数。这是数据库运行方式的一个非常大的变化,可能有几个副作用。如果您尝试以不同的编码添加字符,则可能运气不佳(即您无法将它们存储在数据库中)。所以我不会建议这个解决方案。
通常没有必要在这样的大文本字段上提供任意查询。您可以尝试识别在大文本列上选择的查询,并将它们迁移到CLOB列上的Oracle Text。但这是一个非常大的变化,可能无法使用现有架构或应用程序。您最终可能会遇到一堆“INSTEAD OF”触发器以及一些缺少约束检查(涉及新创建的CLOB列)。
您可以尝试将字符串存储为XML列,而不是CLOB。这些的最大尺寸为4GB。它会损害你的性能,你必须提供INSTEAD OF触发器,你可能会失去一些限制,但它可能对你有用。