我正在使用带有 PL/SQL 的 Oracle 数据库 11g。程序是用C#、.NET 4编写的。
我有一个带有 varchar(4000) 列的表,我想在数据库中存储泰语文本。
我发现当我尝试用泰语存储长度超过 1333 的文本时,Oracle 会抛出异常,尽管最大长度为 4000:
ORA-01461:只能绑定 LONG 值以插入 LONG 列
我还注意到,当我使用较小的限制时,它会按预期工作。即: varchar(10) - 允许长度为 10 的值,更长的文本会引发异常:
ORA-01401插入的值对于列来说太大
根据我已经进行的测试,我可以假设从数字“X”开始,预言机停止计算实际字母的长度。相反,它会乘以最长字母长度值中的字母数(在泰语中,最长字母的长度为 3 - 意味着它就像 3 个字符),因此 1333 * 3 = 3999,我只能添加另一个字符(在类似的语言中)英语)。
我的问题:
- 为什么不同的最大长度的行为会有所不同?
- 在尝试将文本插入表格之前,我能否知道文本的真正限制? (假设文本是泰语和英语,也可能是不同的语言)
重要的提示:因为我需要支持一个非常大且功能正常的系统,所以我无法将数据类型切换为 Club,但它可以解决问题。
感谢您的帮助。
EDIT
我数了一下这 1333 个字符的字节数。它们的字节长度是 2666,仍然小于 4000。我知道最大长度以字节为单位,但我不明白为什么会出现上面的异常。
我用了:System.Text.ASCIIEncoding.Unicode.GetByteCount(text)
检查字节数。
问题
描述 VARCHAR 时,您应该提供一个单位,例如VARCHAR2(200 BYTE)
or VARCHAR2(200 CHAR)
。如果省略单位,则默认为BYTE
(请参阅 Oracle 数据库概念,章节Oracle 数据类型 http://docs.oracle.com/cd/B28359_01/server.111/b28318/datatype.htm#CNCPT1822)。这似乎是一个小细节,但当您具有多字节字符集时,这会变得非常严重。
情况高达11g
不幸的是,VARCHAR2 列的最大大小有硬性限制。它是 4000 字节 (!)(请参阅 Oracle 数据库参考,章节Oracle 数据类型 http://docs.oracle.com/cd/B28359_01/server.111/b28320/limits001.htm#i287903) 直至 Oracle 11g 和 .这是一个硬性限制,没有办法解决这个问题。解决这个问题的唯一方法是使用 CLOB 列。
12c 的解决方案
Oracle 12c 上的情况有所不同。在那里你可以使用参数MAX_STRING_SIZE = EXTENDED
将限制提高到 32767 BYTE(请参阅 Oracle 数据库语言参考,章节数据类型 http://docs.oracle.com/cd/E16655_01/server.121/e17209/sql_elements001.htm#SQLRF50977和 Oracle 数据库参考,章节初始化参数 http://docs.oracle.com/cd/E16655_01/server.121/e17615/refrn10321.htm#REFRN10321)。所以显而易见的解决方案是:升级到 Oracle 12c,设置MAX_STRING_SIZE = EXTENDED
根据文档 http://docs.oracle.com/cd/E16655_01/server.121/e17615/refrn10321.htm#REFRN10321并更改您的表定义。更改表时您可能会丢失一些索引,因为在 12c 之前,索引无法保存超过 4000 BYTE 的 VARCHAR2 值,并且可能仍然存在一些限制。 (我必须检查索引的问题以及是否可以通过重建索引来修复它)。
解决方案:更改数据库编码
您可以尝试更改本机数据库编码(数据库将 CHAR 映射到 BYTE 的方式)。为此,您通常必须创建一个新数据库并为 NLS_CHARACTERSET 提供适当的参数。这是数据库运行方式的一个非常大的变化,并且可能会产生一些副作用。如果您尝试以不同的编码添加字符,您可能会运气不好(即您无法将它们存储在数据库中)。所以我不会建议这个解决方案。
解决方案:切换到CLOB
通常没有必要对如此大的文本字段提供任意查询。您可能会尝试识别在大文本列上选择的查询并将它们迁移到甲骨文文本 http://www.orafaq.com/wiki/Text在 CLOB 列上。但这是一个非常大的变化,对于您现有的架构或应用程序来说可能无法实现。您最终可能会得到一堆“INSTEAD OF”触发器,并且缺少一些约束检查(涉及新创建的 CLOB 列)。
解决方案:使用XML
您可以尝试将字符串存储为 XML 列,而不是 CLOB。这些的最大大小为 4GB。它会损害你的性能,你将不得不提供而不是触发器,并且你可能会失去一些限制,但它可能对你有用。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)