【问题标题】:SQL Server reducing the length of the string to 8000 charactersSQL Server 将字符串长度减少到 8000 个字符
【发布时间】:2019-09-06 07:51:47
【问题描述】:

我正在尝试在列数据类型为NTEXT 的表中插入数据。理想情况下,它应该存储超过 8000 个字符,但在我的情况下,它会减少到 8000 个字符。

我在过程中在运行时进行插入查询。以下是该过程正在进行的示例查询。

INSERT INTO TMPRESULTS SELECT ('A' + ',' + 'B' + ',' + 'C')

A、B、C 等是示例数据,实际数据将在运行时识别,实际内容超过 8000 个字符。用于存储值的变量也定义为'NVARCHAR(MAX)'

但是,当我尝试以下查询时,它确实会在表中插入超过 8000 个字符

INSERT INTO TMPRESULTS SELECT ('ABCdddd................')

我想当我尝试用“+”号连接数据时,sql server 正在将长度减少到 8000。我不能使用CONCAT,因为数据将超过 256 列/参数。

任何想法,为什么要这样做?另外,如果有人可以提供一些替代解决方案,因为我将不得不在运行时进行插入查询。

【问题讨论】:

  • 表达式的类型由其成员给出,而不是由您将存储结果的列/变量给出。如果表达式的任何成员都不是nvarchar(max)类型,则整个表达式将不会在计算时提升为 nvarchar(max),即使结果长度大于 4000/8000。将至少一个表达式成员转换为 nvarchar(max)
  • 嗨@GSerg,我已将数据存储在构成表达式的 NVARCHAR(MAX) 中。不知道我是否应该做其他事情
  • ntext 已被弃用超过 十年。超越时间升级/更换它。

标签: sql sql-server ntext


【解决方案1】:

这记录在+ (String Concatenation) (Transact-SQL) - Remarks:

如果字符串拼接的结果超过了 8,000 字节,结果被截断。但是,如果至少有一个 连接的字符串是大值类型,不会发生截断。

varchar 8,000 字节为 8,000 个字符,nvarchar 为 4,000 个字符。

查询INSERT INTO TMPRESULTS SELECT ('A' + ',' + 'B' + ',' + 'C') 中的所有文字字符串都是非大值类型(实际上,它们都是varchar(1))。如果您将CONVERT/CAST 其中一个发送到varchar(MAX),这将解决问题:

INSERT INTO TMPRESULTS
SELECT (CONVERT(varchar(MAX),'A') + ',' + 'B' + ',' + 'C');

如果您想要 nvarchar,请确保将您的文字字符串也声明为 nvarchar

INSERT INTO TMPRESULTS
SELECT (CONVERT(nvarchar(MAX),N'A') + N',' + N'B' + N',' + N'C');

【讨论】:

    【解决方案2】:

    在 SQL Server 2017 及以后的版本中,CONCAT_WS function 可以轻松执行连接。你也可以阅读CONCAT

    所以,而不是这个:

    INSERT INTO TMPRESULTS SELECT ('A' + ',' + 'B' + ',' + 'C')
    

    我们可以有以下:

    INSERT INTO TMPRESULTS SELECT CONCAT_WS(CAST(N',' AS NVARCHAR(MAX)),'A','B','C'))
    

    我在下面放了来自 SQL Server 2017 的示例以供参考:

    CREATE TABLE #tempValue(BigValue NVARCHAR(MAX))
    
    INSERT INTO #tempValue
    SELECT CONCAT_WS(CAST(N',' AS NVARCHAR(MAX)),REPLICATE('A',4000),REPLICATE('B',4000),REPLICATE('C',4000))
    
    SELECT LEN(BigValue) FROM #tempValue -- 12002
    

    此外,CONCAT_WS 更好的原因如下:

    如果 CONCAT_WS 接收到所有 NULL 值的参数,它将返回 varchar(1) 类型的空字符串。

    CONCAT_WS 在连接期间忽略空值,并且不添加 空值之间的分隔符。

    【讨论】:

    • 虽然使用concat_ws 可能看起来更干净,但它与截断问题无关。 select cast(CONCAT_WS(',', replicate('A', 4000), replicate('B', 4000), replicate('C', 4000)) as nvarchar(max)) 仍会将结果截断为 8000 个字符。
    • @GSerg,谢谢。我已经更新了我的答案。如果其中一个参数为 NVARCHAR(MAX),则 CONCAT_WS 自动将返回类型转换为 NVARCHAR(MAX)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-14
    • 2014-06-23
    相关资源
    最近更新 更多