【问题标题】:Byte-based length of CLR stringCLR 字符串的基于字节的长度
【发布时间】:2013-03-11 19:46:44
【问题描述】:

问题的简短版本:有没有办法计算在 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 个字节,以便在发出 INSERT 语句之前将字符串修剪为 "ábcdefghi" ?

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

【问题讨论】:

    标签: .net string oracle varchar


    【解决方案1】:

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

    【讨论】:

    • +1 -- 无论 Oracle 的编码配置如何,这是唯一可行的答案。
    • 不知道lengthb()这个功能,非常感谢。
    【解决方案2】:

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

    【讨论】:

    • 这是最适合这种情况的答案,因为我只能在问题的数据库方面做这么多。我仅限于更改 C# 应用程序。谢谢大家!
    【解决方案3】:

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

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

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

    select lengthb('ábcdefghij'), vsize('ábcdefghij')
      from dual;
    

    将为结果的两列返回 11。

    【讨论】:

    • +1 for VARCHAR2(10 CHAR)
    • VARCHAR2 如果 DBA 以前考虑过国际字符,那将是一个非常好的主意!顺便说一句,他应该这样做的。我们的葡萄牙语重音字符太多了。
    • @Humberto - VARCHARVARCHAR2 是同义词——如果您愿意,您可以愉快地声明 VARCHAR(10 CHAR) 列(或将现有的 VARCHAR(10 BYTE) 列更改为 VARCHAR(10 CHAR)) .
    【解决方案4】:

    您可以像这样获取字符串的字节长度:

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

    实际上,对于您的示例,它返回 11。

    【讨论】:

    • +1 作为我的答案的代码示例。尽管您可能应该使用静态 Encoding.UTF8 实例,而不是创建新的 UTF8Encoding 实例。 (这样会减少 GC 开销)
    猜你喜欢
    • 2019-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多