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

使用SQL标量值函数拼接结果仅返回最后一条数据的问题

问题根源

在SQL Server里,用SELECT @变量 = @变量 + 表达式这种方式累加字符串,微软官方并没有保证这种行为的确定性。尤其是调用标量值函数的时候,查询优化器可能会调整执行逻辑:先批量算出所有行的函数结果,最后只把最后一条的值赋值给变量,而非逐行叠加。这就是为啥你用内联计算能正常拼接,一调用标量函数就只拿到最后一条结果的原因。

解决办法

给你几个靠谱的实现方案:

1. 使用STRING_AGG(SQL Server 2017及以上版本)

这是官方推荐的字符串聚合方法,语法简洁且行为稳定:

DECLARE @Columns NVARCHAR(MAX);

SELECT @Columns = STRING_AGG([dbo].[getName]([Name], [DeletedDate], DEFAULT), ',') WITHIN GROUP (ORDER BY [Order] DESC)
FROM [dbo].[Items]
WHERE [ProjectId] = 1;

SELECT @Columns;

2. 使用FOR XML PATH(兼容SQL Server 2016及更早版本)

如果你的SQL Server版本较低,用这种经典写法也能实现需求:

DECLARE @Columns NVARCHAR(MAX);

SELECT @Columns = STUFF(
    (SELECT ',' + [dbo].[getName]([Name], [DeletedDate], DEFAULT)
     FROM [dbo].[Items]
     WHERE [ProjectId] = 1
     ORDER BY [Order] DESC
     FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),
    1, 1, ''
);

SELECT @Columns;

3. 将标量函数改为内联表值函数(可选优化)

标量值函数性能普遍较差,还容易触发执行计划异常。改成内联表值函数不仅能解决当前问题,还能提升整体性能:

CREATE OR ALTER FUNCTION getName_ITVF
(
    @name NVARCHAR(200),
    @deletedDate DATETIME2(7) = NULL,
    @suffix NVARCHAR(50) = NULL
)
RETURNS TABLE
AS
RETURN
SELECT QUOTENAME(CONCAT(@name, IIF(@suffix IS NOT NULL, ' ' + @suffix, ''), IIF(@deletedDate IS NOT NULL, CONCAT(' (DELETED - ', FORMAT(@deletedDate, 'dd.MM.yyyy HH:mm:ss'), ')'), ''))) AS Result;

之后用这个函数进行拼接:

DECLARE @Columns NVARCHAR(MAX);

SELECT @Columns = STRING_AGG(f.Result, ',') WITHIN GROUP (ORDER BY [Order] DESC)
FROM [dbo].[Items] i
CROSS APPLY [dbo].[getName_ITVF](i.[Name], i.[DeletedDate], DEFAULT) f
WHERE i.[ProjectId] = 1;

SELECT @Columns;

内容的提问来源于stack exchange,提问作者Sergiu Molnar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 05:35:21