如何逐行执行CTE返回结果中存储的动态SQL语句
批量执行CTE生成的动态SQL语句方案
方案1:直接拼接SQL批量执行(最简单高效)
不需要逐行遍历,直接把所有生成的UPDATE语句拼接成完整的SQL字符串一次性执行,适合不需要单独处理每一行执行结果的场景,效率最高:
DECLARE @TotalQry VARCHAR(MAX) = '' ;WITH CTE AS ( SELECT -- 末尾加分号避免多条SQL拼接时出现语法冲突 Qry = 'UPDATE data_'+ REPLACE(mrp.father_uid, '-', '_')+' SET done = 2 WHERE uid = '''+ CAST(mrp.uid AS VARCHAR(250)) + ''';' FROM [4928_MyProcessDB].dbo.main_result_process mrp WITH (NOLOCK) INNER JOIN [4928_MyProcessDB].dbo.main_result_process_part mrpp WITH (NOLOCK) ON mrp.uid = mrpp.process_uid ) SELECT @TotalQry += Qry + CHAR(13) -- 加换行方便调试时查看生成的SQL结构 FROM CTE -- 先打印查看生成的完整SQL是否符合预期,确认无误后再执行后续的EXEC语句 PRINT @TotalQry -- EXEC sp_executesql @TotalQry
方案2:游标逐行执行(适合需要单独处理每一行的场景)
如果需要记录每一条SQL的执行状态、做错误捕获、重试逻辑,可以用游标遍历逐行执行:
DECLARE @SingleQry VARCHAR(MAX) -- 定义游标读取所有生成的SQL语句 DECLARE QryCursor CURSOR FOR ;WITH CTE AS ( SELECT Qry = 'UPDATE data_'+ REPLACE(mrp.father_uid, '-', '_')+' SET done = 2 WHERE uid = '''+ CAST(mrp.uid AS VARCHAR(250)) + '''' FROM [4928_MyProcessDB].dbo.main_result_process mrp WITH (NOLOCK) INNER JOIN [4928_MyProcessDB].dbo.main_result_process_part mrpp WITH (NOLOCK) ON mrp.uid = mrpp.process_uid ) SELECT Qry FROM CTE OPEN QryCursor FETCH NEXT FROM QryCursor INTO @SingleQry WHILE @@FETCH_STATUS = 0 BEGIN -- 可在此处添加TRY CATCH逻辑捕获单条SQL执行错误,也可打印日志跟踪执行进度 PRINT '正在执行:' + @SingleQry EXEC sp_executesql @SingleQry FETCH NEXT FROM QryCursor INTO @SingleQry END CLOSE QryCursor DEALLOCATE QryCursor
注意事项
- 首次执行前务必先注释
EXEC语句,通过PRINT输出确认生成的SQL语法正确,避免误更新数据 - 动态SQL存在注入风险,请确保
father_uid、uid字段的内容是可控的,不存在恶意输入 - 如果需要保证所有更新操作同时成功或失败,可以在外层添加事务包裹逻辑
内容的提问来源于stack exchange,提问作者Odie
相关产品推荐
相关产品推荐

