如何在tsqlt.ResultSetFilter单元测试中向Azure SQL/SQL存储过程传递表值参数?
用tSQLt.ResultSetFilter测试带表值参数的存储过程:可行方案
你遇到的问题核心是:动态SQL有独立的作用域,外层声明的@Ids表变量无法被tSQLt.ResultsetFilter接收的动态SQL字符串访问,所以会抛出变量未声明的错误。下面是几种可行的解决方法:
方法1:在动态SQL内部创建并填充表值参数
直接把表变量的定义、数据填充和存储过程调用都放到动态SQL字符串里,保证作用域一致,就能正常执行:
DECLARE @execString NVARCHAR(MAX) = ' DECLARE @Ids mytabletype; INSERT INTO @Ids VALUES (NEWID()), (NEWID()); -- 填入测试数据 EXEC Myproc @Ids; '; EXEC tsqlt.ResultsetFilter 2, @execString;
如果测试数据是在外层动态生成的,可以先把数据转换成字符串拼接到动态SQL中:
DECLARE @Ids mytabletype; INSERT INTO @Ids VALUES (NEWID()), (NEWID()); -- 生成VALUES子句的内容 DECLARE @Values NVARCHAR(MAX); SELECT @Values = STRING_AGG('(''' + CAST(myid AS VARCHAR(36)) + ''')', ',') FROM @Ids; -- 拼接完整的动态SQL DECLARE @execString NVARCHAR(MAX) = ' DECLARE @Ids mytabletype; INSERT INTO @Ids VALUES ' + @Values + '; EXEC Myproc @Ids; '; EXEC tsqlt.ResultsetFilter 2, @execString;
方法2:用全局临时表传递数据
全局临时表(以##开头)在整个会话中可见,动态SQL可以直接访问。利用这一点传递表值参数的数据:
-- 创建全局临时表,结构与表值类型一致 CREATE TABLE ##TestIds ([myid] UNIQUEIDENTIFIER NOT NULL); INSERT INTO ##TestIds VALUES (NEWID()), (NEWID()); -- 动态SQL内部读取临时表数据,传给存储过程 DECLARE @execString NVARCHAR(MAX) = ' DECLARE @Ids mytabletype; INSERT INTO @Ids SELECT * FROM ##TestIds; EXEC Myproc @Ids; '; EXEC tsqlt.ResultsetFilter 2, @execString; -- 测试完成后清理临时表 DROP TABLE ##TestIds;
关键说明
- 动态SQL拥有独立的执行上下文,外层的局部变量(包括表变量)无法直接在动态SQL中引用,这是你最初报错的根本原因。
- 以上两种方法都能让存储过程正确接收到表值参数,同时通过
tSQLt.ResultsetFilter获取第二个结果集。
内容的提问来源于stack exchange,提问作者stevie_c
相关产品推荐
相关产品推荐

