You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

对NVARCHAR(max)列调用Left函数后存入NVARCHAR(x)列是否安全?

NVARCHAR与LEFT函数的行为探讨

问题背景

一直以来,我都被NVARCHAR(x)的参数是字符数这一常见误解困扰,现深入探讨相关问题:

假设有FOO_PERM_TABLE表中的NVARCHAR(max)类型列FOO_PERM_COL,执行以下代码是否会失败?

CREATE TABLE #FOO_TEMP_TABLE
(
   FOO_TEMP_COL NVARCHAR(1000) NOT NULL
)

INSERT INTO #FOO_TEMP_TABLE
SELECT Left(FOO_PERM_COL, 1000)
FROM FOO_PERM_TABLE

要求:若代码可能抛出异常,请给出失败示例;若排序规则有影响,请说明;若不会失败,请提供文档依据支持论点。

我认为LEFT函数的文档未阐述完整信息:文档称其会将列截断至指定字符数,但实际测试显示其行为不止于此。若LEFT仅截断至指定字符数,SELECT LEFT(N'🙏', 1)应返回输入的Unicode字符,但实际并非如此。文档中以下内容与此密切相关:

integer_expression参数将UTF-16代理字符计为一个字符。


问题解答

1. 代码是否会失败?

这段代码不会失败。

根据Microsoft官方文档,当输入为NVARCHAR类型时,LEFT函数返回NVARCHAR类型结果,其长度由第二个参数指定。LEFT(FOO_PERM_COL, 1000)返回的结果最多占用1000个UTF-16代码单元,恰好匹配目标列NVARCHAR(1000)的容量上限,因此插入操作不会触发长度超限异常。

2. LEFT函数的行为细节

NVARCHAR(x)中的x代表的是UTF-16代码单元的数量,而非人们直觉中的实际Unicode字符数——这正是核心误解所在。

文档中提到的「integer_expression参数将UTF-16代理字符计为一个字符」是关键:UTF-16编码中,部分复杂字符(如表情符号🙏)需要用两个代码单元(代理对)组合表示,但LEFT的第二个参数会把每个代码单元单独算作一个计数单位。因此SELECT LEFT(N'🙏', 1)只会返回该字符的第一个代理单元,这是一个无效的单独代理字符,而非完整的🙏符号。

这一行为是LEFT基于UTF-16代码单元计数的固有特性,只是文档未明确关联NVARCHAR的代码单元定义,才导致了误解。

3. 排序规则的影响

排序规则不会改变LEFT函数的长度计数逻辑。排序规则主要负责字符的比较、排序和显示格式,与UTF-16代码单元的存储和计数方式无关,无论使用何种排序规则,LEFT都以代码单元为计数基准。


内容的提问来源于stack exchange,提问作者J. Mini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 18:52:46