如何将SQL多行多列结果存入nvarchar(max)存储过程输出参数?
解决多列多行数据拼接为字符串的存储过程问题
错误原因分析
你遇到的错误是因为sp_executesql要求@statement和@params参数必须是nvarchar/nchar/ntext类型(推荐用nvarchar(max)),如果你的动态SQL语句变量用了varchar类型,或者参数声明不符合要求,就会触发这个报错。另外,处理多列多行拼接其实不需要依赖动态SQL,用更简洁的方法就能实现。
正确实现方案
1. 先确认表类型定义
注意:user是SQL Server关键字,建议改名比如udt_User避免语法冲突,示例定义如下:
CREATE TYPE dbo.udt_User AS TABLE ( Id INT, No_user VARCHAR(50), Name NVARCHAR(100) ); GO
2. 存储过程实现(SQL Server 2017+ 推荐用STRING_AGG)
用STRING_AGG直接拼接每行的多列数据,无需动态SQL,代码简洁高效:
CREATE PROCEDURE dbo.some_procedure @OutputResult NVARCHAR(MAX) OUTPUT AS BEGIN SET NOCOUNT ON; -- 声明表类型变量并插入测试数据 DECLARE @userList dbo.udt_User; INSERT INTO @userList (Id, No_user, Name) VALUES (1, 'U001', '张三'), (2, 'U002', '李四'), (3, 'U003', '王五'); -- 拼接多列多行数据:每行格式为 "Id:X, 账号:Y, 姓名:Z",用换行分隔 SELECT @OutputResult = STRING_AGG( CONCAT('Id:', Id, ', 账号:', No_user, ', 姓名:', Name), CHAR(13) + CHAR(10) -- 可替换为';'等其他分隔符 ) FROM @userList; END GO
3. 老版本SQL Server(2016及以前)用STUFF+FOR XML PATH
针对低版本数据库,用传统拼接方式实现:
CREATE PROCEDURE dbo.some_procedure @OutputResult NVARCHAR(MAX) OUTPUT AS BEGIN SET NOCOUNT ON; DECLARE @userList dbo.udt_User; INSERT INTO @userList (Id, No_user, Name) VALUES (1, 'U001', '张三'), (2, 'U002', '李四'), (3, 'U003', '王五'); -- 拼接多列数据,用STUFF去掉开头的分隔符 SELECT @OutputResult = STUFF( ( SELECT CHAR(13) + CHAR(10) + CONCAT('Id:', Id, ', 账号:', No_user, ', 姓名:', Name) FROM @userList FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)'), 1, 2, '' -- 去掉开头的换行符(CHAR(13)+CHAR(10)占2个字符) ); END GO
4. 如果必须用动态SQL(不推荐)
若因特殊场景必须使用动态SQL,需确保@statement和参数声明均为nvarchar类型:
CREATE PROCEDURE dbo.some_procedure @OutputResult NVARCHAR(MAX) OUTPUT AS BEGIN SET NOCOUNT ON; DECLARE @userList dbo.udt_User; INSERT INTO @userList (Id, No_user, Name) VALUES (1, 'U001', '张三'), (2, 'U002', '李四'), (3, 'U003', '王五'); DECLARE @sql NVARCHAR(MAX); -- 必须为NVARCHAR类型 SET @sql = N' SELECT @Result = STRING_AGG( CONCAT(''Id:'', Id, '', 账号:'', No_user, '', 姓名:'', Name), CHAR(13)+CHAR(10) ) FROM @userList'; -- 执行动态SQL,参数声明必须是NVARCHAR类型 EXEC sp_executesql @sql, N'@userList dbo.udt_User READONLY, @Result NVARCHAR(MAX) OUTPUT', @userList = @userList, @Result = @OutputResult OUTPUT; END GO
关键注意事项
- 避免使用SQL Server关键字(如
user)作为表类型、变量名称,防止语法冲突。 - 动态SQL中,字符串内的单引号需要用两个单引号转义(
'')。 sp_executesql的@statement和@params参数必须是nvarchar类型,不能用varchar。
内容的提问来源于stack exchange,提问作者1029Coder
相关产品推荐
相关产品推荐

