我已经阅读了有关 varchar 与 nvarchar 的所有内容。但我没有看到我认为简单的问题的答案。如何确定 nvarchar 列的长度?对于 varchar 来说非常简单:例如,我的描述可以有 100 个字符,所以我定义了 varchar(100)。现在我被告知我们需要国际化并支持任何语言。这是否意味着我需要将“描述”列更改为 nvarchar(200),即长度加倍? (我暂时忽略了与国际化相关的所有其他问题。)
有这么简单吗?
来自微软网站:
一个常见的误解是认为使用 nchar(n) 和 nvarchar(n),n 定义字符数。但是,在 nchar(n) 和 nvarchar(n) 中,n 以 byte-pairs (0-4,000) 的形式定义字符串长度。 n 从不定义可以存储的字符数。这类似于 char(n) 和 varchar(n).
的定义之所以会出现这种误解,是因为当使用 Unicode 范围 0 到 65,535 中定义的字符时,每个字节对可以存储一个字符。但是,在较高的 Unicode 范围(65,536 到 1,114,111)中,一个字符可以使用两个字节对。例如,在定义为 nchar(10) 的列中,数据库引擎可以存储使用一个字节对(Unicode 范围 0 到 65,535)的 10 个字符,但使用两个字节对(Unicode 范围)时少于 10 个字符65,536 至 1,114,111)。有关 Unicode 存储和字符范围的更多信息,请参阅UTF-8 和 UTF-16 之间的存储差异。
@Musa Calgar - 完全正确。该链接包含此问题答案的信息。
但是为了确保问题本身清楚,我们正在讨论当我们查看给定表的列定义时看到的“长度”属性,对吧?这是每列分配的存储空间。另一方面,如果我们想知道给定时刻表中给定字符串的字符数,您可以: “从 myTable 中选择 myColumn,LEN(myColumn)”
但是如果需要存储长度,您可以使用 SSMS 将表名称拖到查询窗口中,突出显示它,然后使用“Alt-F1”查看每列定义的长度。
作为示例,我创建了一个像这样指定排序规则的表。 (Latin1_General_100_CI_AS_SC 允许使用补充字符 - 即占用超过 2 个字节的字符):
CREATE TABLE [dbo].[TestTable1](
[col1] [varchar](10) COLLATE Latin1_General_100_CI_AS,
[col2] [nvarchar](10) COLLATE Latin1_General_100_CI_AS_SC,
[col3] [nvarchar](10) COLLATE Latin1_General_100_CI_AS
) ON [PRIMARY]
长度显示如下(在查询窗口中突出显示并按 Alt-F1):
Column_Name Type Length [...] Collation
col1 varchar 10 Latin1_General_100_CI_AS
col2 nvarchar 20 Latin1_General_100_CI_AS_SC
col3 nvarchar 20 Latin1_General_100_CI_AS
如果您在 varchar 和 nvarchar 字段中插入 ASCII 字符,则将允许您在所有字段中插入 10 个字符。如果您尝试在这些字段中输入超过 10 个字符,将会出现错误:
“字符串或二进制数据将被截断。 该声明已终止。”
如果插入“ā”等非 ASCII 字符,您仍然可以在每个字符中放入 10 个字符,但 SQL Server 会将进入 col1 的值转换为适合 1 字节的最接近的已知字符。在这种情况下,“ā”将转换为“a”。
但是,如果您插入需要 4 个字节来存储的字符,例如“𠜎”,则只允许您将其中的 5 个字符放入 varchar 和 nvarchar 字段中。超过此值将导致上面显示的截断错误。 varchar 字段将显示问号,因为它没有可以将该输入转换为的单字节字符。
因此,当您插入其中五个“𠜎”时,使用 len(
col1 len(col1) col2 len(col2) col3 len(col3)
?????????? 10 𠜎𠜎𠜎𠜎𠜎 5 𠜎𠜎𠜎𠜎𠜎 10
所以 col2 的长度显示 5 个字符,因为增补字符是在创建表时定义的(参见上面的 CREATE TABLE DDL 语句)。但是,col3 的排序规则没有 _SC,因此我们插入的 5 个字符的长度显示为 10。 请注意,col1 有十个问号。如果我们使用 _SC 排序规则而不是非补充排序规则定义 col1 varchar,它的行为方式是相同的。