基于字节的CLR字符串长度

时间:2013-03-11 19:46:45

标签: .net string oracle varchar

问题的简短版本:有没有办法计算在Oracle数据库的VARCHAR(n)列中存储字符串字符所需的字节数?

更长版本:以下Oracle SQL脚本将在第三个语句中失败。它会尝试在VARCHAR(10)列中插入10个字符;但是,其中一个字符是具有强烈重音的A.

CREATE TABLE TESTTABLE (NAME VARCHAR(10) NULL);

INSERT INTO TESTTABLE (NAME) VALUES ('abcdefghij');
--1 rows inserted.

INSERT INTO TESTTABLE (NAME) VALUES ('ábcdefghij');
--ORA-12899: value too large for column "ACME"."TESTTABLE"."NAME" (actual: 11, maximum: 10)

我的C#应用​​程序将字符串存储在Oracle数据库中,我不能只将列类型更改为NVARCHAR2(10),这将起作用。应用程序应该将任何较大的字符串修剪为10个字符的限制,因此Oracle不会抱怨它的长度。但基于String.Length的修剪是一种非常天真的策略:它会盲目地将“ábcdefghij”保留为完整的10个CLR字符。

如何检测'á'将占用数据库行中的2个字节,以便在发出{{1}之前将字符串修剪为“ábcdefghi”声明?

编辑:此问题类似于Best way to shorten UTF8 string based on byte length

4 个答案:

答案 0 :(得分:5)

Oracle函数length(string)返回字符数,lengthb(string)返回字节数。

答案 1 :(得分:4)

这取决于Oracle设置使用的编码。您可以使用相应的System.Text.Encoding实例将字符串实例转换为字节数组,例如System.Text.Encoding.UTF8。 (您正在寻找“GetBytes”方法)

答案 2 :(得分:4)

默认情况下,VARCHAR2(10)分配10个字节的存储空间,根据数据库字符集和数据,这些字节可能等于或不等于10个字符。但是,您可以声明该列,以便它始终存储10个字符。

当您使用可变宽度字符集时,您几乎总是希望使用字符长度语义VARCHAR2(10 CHAR)来声明该列。然后,无论您是否碰巧有一些字符需要超过1个字节的存储空间,您始终可以存储10个字符。

如果由于某种原因而无法使用字节长度语义声明列,则可以使用LENGTHBVSIZE函数以字节为单位返回字符串的长度。

select lengthb('ábcdefghij'), vsize('ábcdefghij')
  from dual;
对于结果的两列,

将返回11。

答案 3 :(得分:1)

你可以得到字符串的长度,如下所示:

UTF8Encoding Encoding = new UTF8Encoding();
byte[] UTF8String = Encoding.GetBytes("ábcdefghij");
int StringLenght = UTF8String.Length

事实上,对于你的例子,它返回11。