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

2024-03-23

我正在使用带有 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,我只能添加另一个字符(在类似的语言中)英语)。

我的问题:

  1. 为什么不同的最大长度的行为会有所不同?
  2. 在尝试将文本插入表格之前,我能否知道文本的真正限制? (假设文本是泰语和英语,也可能是不同的语言)

重要的提示:因为我需要支持一个非常大且功能正常的系统,所以我无法将数据类型切换为 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(使用前将#替换为@)

VARCHAR 最大长度为 4000,但只能存储 2666 字节长的泰语文本 的相关文章

  • ORACLE:未找到数据——但数据存在

    调试包过程 当实际上有数据时却找不到数据 仅测试 SELECT SELECT trim trailing from GL SECURITY as DUMMY FROM b2k user b2k WHERE sms username FUCH
  • 获取一组记录之间的时间差

    我有一个具有以下结构的表 ID ActivityTime Status 19 2013 08 23 14 52 1 19 2013 08 23 14 50 1 19 2013 08 23 14 45 2 19 2013 08 23 14 3
  • postgresql 中的锁定表

    我有一个名为 games 其中包含一个名为 title 该列是唯一的 数据库中使用PostgreSQL 我有一个用户输入表单 允许他插入新的 game in games 桌子 插入新游戏的功能会检查之前输入的游戏是否存在 game 与相同的
  • 如何在 DataColumn.Expression 中使用 IF/ELSE 或 CASE?

    我有一个包含 1 列的表 状态 我想添加另一列名为 Action 的列 其值如下 如果 Status Yes 则 Action Go 否则 Action Stop 我使用以下代码添加到 操作 列中 但它不起作用 myDataTable Co
  • Postgres 中 -Infinity 和 Infinity 的适当值

    在一种情况下 我们必须在 Postgres DB 中存储 无穷大和 无穷大的值 应该考虑什么合适的值 如果没有 请建议最合适的替代方案 你实际上可以使用 infinity and infinity for FLOAT4 and FLOAT8
  • JDBC 时间戳和日期 GMT 问题

    我有一个 JDBC 日期列 如果我使用 getDate 则会得到 date 仅部分2009 年 10 月 2 日但如果我使用 getTimestamp 我会得到完整的 date 2009 年 10 月 2 日 13 56 78 890 这正
  • 每行中非空列的计数

    我有一个包含 4 列的表 在第 5 列中我想存储前 4 列中有多少个非空列的计数 例如 其中 X 是任意值 Column1 Column2 Column3 Column4 Count X X NULL X 3 NULL NULL X X 2
  • PLS-00103:遇到符号“;”当预期出现以下情况之一时:

    我正在尝试插入用户安全问题的答案 以用于密码重置功能 Ellucian 横幅 v8 提供了一个用于运行此 API 的 API 我对他们的 API 非常陌生 从下面的错误消息来看 我还远远没有正确运行它 任何帮助表示赞赏 我尝试在 Oracl
  • MySQL 最佳实践:SELECT 子递归尽可能提高性能?

    我想选择一个根项目及其子项 使其性能尽可能高 我更喜欢使用嵌套集模型 但这次表结构遵循邻接模型 有关嵌套集和邻接模型的更多信息 http mikehillyer com articles managing hierarchical data
  • 如何在 SQL Server 中保持数据行内

    我正在尝试找出如何检测数据是否在VARCHAR n SQL Server 2008 中的列存储在行内或行外 有谁知道如何做到这一点 另外 如果我们需要数据 有没有办法将数据保持在行中 要查看某个值是行内还是行外 您可以使用DBCC PAGE
  • 我应该定义索引(A)和索引(B),还是索引(A,B),或者两者都定义?

    在我的表中 我有两个密切相关的列 A 和 B 我应该考虑哪些因素来决定是否创建 索引 A 和索引 B 索引 A B 以上两者 如果我 仅使用类似的查询where A 5 and B 10 并且从不喜欢where A 5 也可以使用类似的查询
  • 手动更改postgresql中查询的执行计划?

    是否可以在postgresql中手动更改执行计划的操作顺序 例如 如果我总是想在过滤之前进行排序操作 尽管这在 postgresql 的正常使用中没有意义 是否可以通过例如手动强制执行该操作改变运营的内部成本 如果我实现自己的功能呢 是否可
  • Postgresql 串行错误自动增量

    我在 postgresql 上遇到问题 我认为 postgresql 中有一个错误 我错误地实现了一些东西 有一个表包括colmn1 primary key colmn2 unique colmn3 插入一行后 如果我尝试使用现有的另一次插
  • Sql Server 的夏令时

    我们正在使用一个以 C Unix 格式存储日期的旧应用程序 C 时间基本上是自 1970 年 1 月 1 日以来的秒数 日期以整数形式存储在 SQL Server 数据库中 我正在为使用这些日期的报告编写视图 到目前为止 我正在使用以下命令
  • 唯一约束与唯一索引?

    之间有区别吗 CREATE TABLE p product no integer name text UNIQUE price numeric and CREATE TABLE p product no integer name text
  • nvarchar 值“3001822585”的转换溢出了 int 列

    我使用以下方法将 Excel 文件导入到 SQL Server Excel 文件将所有值作为字符串 我可以导入文件 除了Barcode SalePrice and Price2 我收到错误 nvarchar 值 3001822585 条形码
  • Magento 设置脚本中的 ALTER TABLE 不使用 SQL

    乔纳森 戴 https stackoverflow com users 336905 jonathan day says 更新不应采用以下形式 SQL命令 我没遇到过 任何 DDL 或 DML 语句不能 通过 Magento 的配置执行 结
  • Oracle 按月滚动或运行总计

    目标 每个月末所有报表的滚动 运行总计 Code select TRUNC ACTHX STMT HX STMT DATE MM AS MNTH COUNT ACTHX INVOICE as STMTS from ACTHX group b
  • 如何使用第二行中的值填充第一行中的空值?

    我正在尝试编写一个查询 仅显示每个名称的第一行 但这些行的标题为空 因此我想从紧邻的下一行中提取它们的标题 table1 Name Title Row Dan NULL 1 Dan Engineer 2 Dan Developer 3 Ja
  • 最近邻居的 Postgis SQL

    我正在尝试计算最近的邻居 为此 我需要传递一个参数来限制与邻居的最大距离 例如 半径1000米内最近的邻居是哪些 我做了以下事情 我用数据创建了表 id name latitude longitude 之后 我执行了以下查询 SELECT

随机推荐