SQL循环遍历多列插入拼接串至同行及动态列名赋值需求
嘿,我来帮你搞定这两个SQL需求,都是动态列相关的场景,直接上实用解决方案:
需求2:给动态无名列临时表分配拆分后的列名
这个场景必须用动态SQL实现,因为列的数量和名称都是动态的。以下是针对SQL Server的具体实现:
前提说明
假设你的临时表#Temp是通过SELECT INTO这类方式生成的,系统默认列名为Column1、Column2……ColumnN;同时你有一个逗号分隔的列名字符串变量@stringlist。
方案1:SQL Server 2016+(支持STRING_SPLIT和STRING_AGG)
DECLARE @stringlist NVARCHAR(MAX) = 'company_no,emp_no,emp_name,emp_type,salary_type'; DECLARE @sql NVARCHAR(MAX); -- 拆分列名字符串并生成列别名映射 WITH ColumnNames AS ( SELECT value AS ColumnName, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS RowNum FROM STRING_SPLIT(@stringlist, ',') ) SELECT @sql = STRING_AGG(QUOTENAME('Column' + CAST(RowNum AS NVARCHAR)) + ' AS ' + QUOTENAME(ColumnName), ', ') FROM ColumnNames; -- 生成并执行完整查询 SET @sql = 'SELECT ' + @sql + ' FROM #Temp'; EXEC sp_executesql @sql;
方案2:兼容旧版本SQL Server(无内置拆分/聚合函数)
先创建一个自定义拆分函数:
CREATE FUNCTION dbo.SplitString (@str NVARCHAR(MAX), @delimiter CHAR(1)) RETURNS @result TABLE (Value NVARCHAR(MAX), RowNum INT) AS BEGIN DECLARE @pos INT, @prevPos INT = 0, @rowNum INT = 1; SET @pos = CHARINDEX(@delimiter, @str); WHILE @pos > 0 BEGIN INSERT INTO @result VALUES(SUBSTRING(@str, @prevPos + 1, @pos - @prevPos - 1), @rowNum); @prevPos = @pos; @pos = CHARINDEX(@delimiter, @str, @pos + 1); @rowNum += 1; END INSERT INTO @result VALUES(SUBSTRING(@str, @prevPos + 1, LEN(@str) - @prevPos), @rowNum); RETURN; END
再用游标拼接动态SQL:
DECLARE @stringlist NVARCHAR(MAX) = 'company_no,emp_no,emp_name,emp_type,salary_type'; DECLARE @sql NVARCHAR(MAX) = ''; DECLARE @columnName NVARCHAR(MAX), @rowNum INT; DECLARE cur CURSOR FOR SELECT Value, RowNum FROM dbo.SplitString(@stringlist, ','); OPEN cur; FETCH NEXT FROM cur INTO @columnName, @rowNum; WHILE @@FETCH_STATUS = 0 BEGIN IF @sql <> '' SET @sql += ', '; SET @sql += QUOTENAME('Column' + CAST(@rowNum AS NVARCHAR)) + ' AS ' + QUOTENAME(@columnName); FETCH NEXT FROM cur INTO @columnName, @rowNum; END CLOSE cur; DEALLOCATE cur; SET @sql = 'SELECT ' + @sql + ' FROM #Temp'; EXEC sp_executesql @sql;
需求1:遍历N列表格列,拼接字符串插入同一行
这个需求是把一行中所有列的内容(或列名+内容)拼接成一个字符串,放在当前行的新列中。同样用动态SQL处理:
方案1:SQL Server 2017+(支持STRING_AGG)
DECLARE @sql NVARCHAR(MAX); DECLARE @tableName NVARCHAR(MAX) = 'YourTable'; -- 替换成你的表名 DECLARE @schemaName NVARCHAR(MAX) = 'dbo'; -- 替换成你的schema -- 生成拼接逻辑:这里是「列名:值」的格式,可根据需求调整 SELECT @sql = STRING_AGG( '''' + COLUMN_NAME + ': '', CAST(' + QUOTENAME(COLUMN_NAME) + ' AS NVARCHAR(MAX))', ', ' ) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND TABLE_SCHEMA = @schemaName; -- 生成完整查询,新增拼接后的列 SET @sql = 'SELECT *, CONCAT(' + @sql + ') AS ConcatenatedString FROM ' + QUOTENAME(@schemaName) + '.' + QUOTENAME(@tableName); EXEC sp_executesql @sql;
方案2:兼容旧版本SQL Server
用游标拼接动态SQL:
DECLARE @sql NVARCHAR(MAX) = ''; DECLARE @tableName NVARCHAR(MAX) = 'YourTable'; -- 替换成你的表名 DECLARE @schemaName NVARCHAR(MAX) = 'dbo'; -- 替换成你的schema DECLARE @columnName NVARCHAR(MAX); DECLARE cur CURSOR FOR SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND TABLE_SCHEMA = @schemaName; OPEN cur; FETCH NEXT FROM cur INTO @columnName; WHILE @@FETCH_STATUS = 0 BEGIN IF @sql <> '' SET @sql += ', '; -- 这里是「列名:值」的格式,若只需拼接值,改为 QUOTENAME(@columnName) 即可 SET @sql += '''' + @columnName + ': '', CAST(' + QUOTENAME(@columnName) + ' AS NVARCHAR(MAX))'; FETCH NEXT FROM cur INTO @columnName; END CLOSE cur; DEALLOCATE cur; SET @sql = 'SELECT *, CONCAT(' + @sql + ') AS ConcatenatedString FROM ' + QUOTENAME(@schemaName) + '.' + QUOTENAME(@tableName); EXEC sp_executesql @sql;
内容的提问来源于stack exchange,提问作者Koo SengSeng
相关产品推荐
相关产品推荐

