TSQL 循环中如何动态传递表名给tSQLt实现批量非空校验
实现方案
核心逻辑
你搭建的循环遍历框架本身没有问题,缺失的环节是每轮迭代先把当前序号对应的表名字符串取出来,存入独立变量后传入tSQLt断言存储过程——不需要复杂的动态SQL拼接,通过临时表查询取值就能实现和C#数组下标取值完全一致的效果。
逐段补全说明
- 循环开始前需要额外声明一个独立变量,用来承接每轮从临时表查询得到的表名
- 每轮循环触发时,通过当前的自增计数器匹配临时表的Id字段,把对应行的表名存入上述变量
- 直接把这个变量作为参数传给
tSQLt.AssertNonEmptyTable即可,不需要额外拼接字符串
完整可运行代码
-- 原有待校验表清单临时表逻辑保留 DROP TABLE IF EXISTS #SourceTables CREATE TABLE #SourceTables ( Id INT, TableName NVARCHAR(200) -- 适配SQL Server对象名长度限制,不需要用MAX ) INSERT INTO #SourceTables VALUES (1, 'src.fusion_sec_assigned_workgroup'), (2, 'src.fusion_sec_user_account'), (3, 'src.fusion_sec_user_in_organisation'), (4, 'src.BULL_OHMS_WORKGROUPS'), (5, 'src.fusion_rep_extension_request_reason'), (6, 'src.fusion_rep_extension_request_trade'), (7, 'src.fusion_rep_job_ext_request_reason'), (8, 'src.fusion_rep_job_ext_request_trade'), (9, 'src.bull_rep_audit_adhoc_jobs'), (10, 'src.BULL_REP_AUDIT_JOB_NONSORS'), (11, 'src.bull_REP_AUDIT_JOB_SORS'), (12, 'src.BULL_REP_REASON_CODES') -- 原有计数器逻辑保留 DECLARE @ctr INT = 1 DECLARE @length INT = (SELECT COUNT(*) FROM #SourceTables) -- 新增:声明存储当前待校验表名的变量 DECLARE @CurrentTableName NVARCHAR(200) WHILE (@ctr <= @length) BEGIN PRINT '正在校验第' + CAST(@ctr AS VARCHAR(10)) + '个表:' + (SELECT TableName FROM #SourceTables WHERE Id = @ctr) -- 取出当前迭代对应的表名,存入变量 SELECT @CurrentTableName = TableName FROM #SourceTables WHERE Id = @ctr -- 直接把表名变量传入断言存储过程 EXEC tSQLt.AssertNonEmptyTable @TableName = @CurrentTableName SET @ctr = @ctr + 1 END
常见踩坑提醒
- 别绕弯路拼动态SQL传参:很多人会第一反应写
EXEC ('tSQLt.AssertNonEmptyTable ''' + @CurrentTableName + ''''),这种写法会让断言逻辑脱离tSQLt的测试会话上下文,最后测试框架根本收集不到这个断言的执行结果,白跑一圈。直接把变量当存储过程入参传就完全合规。 - 表名必须带schema前缀:你存的所有表名都是
src.xxx的格式,这个是正确的,如果去掉src.前缀,tSQLt会默认在当前登录账号的默认schema下搜表,大概率会报对象找不到。 - 注意排序规则的大小写问题:如果你的库是大小写敏感的排序规则,临时表里存的表名、schema名的大小写必须和实际库对象完全匹配,哪怕差一个字母的大小写,都会触发对象不存在的报错。
内容的提问来源于stack exchange,提问作者k_rollo
相关产品推荐
相关产品推荐

