【问题标题】:Sql Server - does VARCHAR length indicate max number of characters or number of bytes?Sql Server - VARCHAR 长度是否表示最大字符数或字节数?
【发布时间】:2018-05-28 01:49:27
【问题描述】:

对于类型为

的 SQL Server 列

VARCHAR(100)

在插入列之前,我想确保插入的值不大于 100。该数字是指定它可以存储的最大字符数,还是它是数字它可以存储多少字节的字符数据

我问的原因是一些 unicode 特殊字符使用了多个字节。因此,用 unicode 编码的 100 个字符的字符串可能会占用超过 100 个字节。

既然varchar是用于ASCII编码的,那么任何ASCII字符是否有可能占用一个以上的字节(这可能需要检查字节长度)?

(编辑:根据我对这个问题的反馈,我看到 varchar 应该用于 ASCII,nvarchar 应该用于 unicode。)

【问题讨论】:

  • 如果您正在处理 unicode,那么您应该改用 nvarhcar
  • 不清楚您所说的“某些特殊字符使用超过一个字节”是什么意思,因为 VARCHAR 不是这种情况,它是为 ASCII 字符设计的。

标签: c# sql-server string


【解决方案1】:

我从研究这个问题中学到了一些东西!

在 SQL Server 中

  1. nvarchar 占用双倍存储空间,因为它使用两字节字符集 UNICODE UCS-2

n 定义字符串长度...存储大小(以字节为单位)是输入数据实际长度的两倍 + 2 个字节。

这告诉我为nvarchar 指定的长度肯定是字符数,而不是字节数。

  1. varchar是一字节一字符存储,存储单字节非unicode字符数据。

n 定义字符串长度...存储大小是输入数据的实际长度 + 2 个字节。

我会从这两个陈述中推断出varcharnvarchar 列的长度指示的数字确实是字符数。

短语length of the data entered 有点模棱两可,但从这两个描述中我认为可以合理地得出结论,它们表示输入的字符数。

如果您有可能接收和存储两字节字符数据,请始终选择nvarchar over varchar,即使性能可能会受到影响。链接的问题和答案有助于了解原因。

底线是SQL Server 将varcharnvarchar 列的长度表示为输入的字符数。它将为您处理存储。不用担心字节!

注意:Adding to the confusion 是 Oracle 允许您在本机类型 VARCHAR2 中指定字节长度或字符长度:

Oracle VARCHAR2

随着多字节字符集的使用越来越多的支持 全球化数据库带来的字节问题不再等同于 字符。

VARCHAR2 和 CHAR 类型支持两种指定长度的方法:

以字节为单位:VARCHAR2(10 字节)。这将支持最多 10 个字节的数据, 在一个多字节字符中可能少至两个字符 套。以字符为单位:VARCHAR2(10 个字符)。这将支持最多 10 个 数据的字符,最多可以是 40 字节的信息。

而且看起来默认是字节!

这似乎不仅仅让我们感到困惑:

Oracle varchar2 - bytes or chars

因此,如果您来自 Oracle 世界,您可能会认为这在任何地方都是正确的。如果您来自 SQL Server 世界,您可能不会意识到情况就是这样!

在 SQL Server 中

让我感到困惑的是UTF-8 unicode 字符最多可以占用 6 个字节,而很多只占用 1 个字节!然而,docs 说每个字符恰好占用两个字节。

真的……How many bytes does one Unicode character take?

答案:SQL Server 使用的是UNICODE UCS-2

使用单个代码值(定义为一个或多个数字表示 一个代码点),每个字符在 0 到 65,535 之间,并且允许 恰好两个字节(一个 16 位字)来表示该值。

这解释了为什么 SQL Server 可以根据字符串的长度拥有特定数量的空间。 所有字符在一个 nvarchar 列中占用两个字节!

【讨论】:

    【解决方案2】:

    正确的做法是检查长度

    if (myString.Length > 100)
    {
        MessageBox.Show("String too long");
        return; 
    }
    

    .NET string 已经是 Unicode,可以保存你拥有的任何字符。 相反,varchar 数据类型只是 ASCII 类型,不支持 Unicode。您需要做的是将 db 列声明为nvarchar,一切都会顺利进行。不要做任何疯狂的事情。

    【讨论】:

      【解决方案3】:

      GetByteCount 用于适当的编码器——在本例中,ASCII 用于 VarChar,Unicode 用于 NVarChar)。

          var s = "This is a string";
          var len1 = s.Length;
          var len2 = System.Text.Encoding.Unicode.GetByteCount(s);
          var len3 = System.Text.Encoding.ASCII.GetByteCount(s);
          Console.WriteLine("'{0}' has {1} characters and is {2} bytes with Unicode encoding and {3} bytes with ASCII encoding.", s, len1, len2, len3);
      

      输出:

      'This is a string' has 16 characters and is 32 bytes with Unicode encoding and 16 bytes with ASCII encoding.
      

      【讨论】:

      • 这是NVARCHAR 的合适编码器,而不是普通的VARCHAR。对于 VARCHAR,应使用 System.Text.Encoding.ASCII
      • 已修订。没有仔细阅读问题。我想不出任何多字节 ASCII 字符,所以我很惊讶这就是 OP 所要求的。
      • 感谢@JohnWu,这很有帮助。后续问题 - 可能没有任何多字节 ASCII 字符,但是如果将多字节 unicode 字符插入varchar 列会发生什么?
      • 您可以尝试将 unicode 字符插入普通的 varchar,但任何不在代码页上的字符都会以问号结尾。不推荐。
      【解决方案4】:

      如果它已经是一个字符串,你只需要确保该字符串的长度不超过 100 个字符

      【讨论】:

      • 这属于评论。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-14
      • 2012-03-24
      • 2015-03-27
      • 2011-02-14
      • 1970-01-01
      • 2013-08-27
      相关资源
      最近更新 更多