Sql server 在同一个表中动态解析列值
我有一个存储过程,它接受可输入的Sql server 在同一个表中动态解析列值,sql-server,sql-server-2008,Sql Server,Sql Server 2008,我有一个存储过程,它接受可输入的作为参数: create table inputTable (id int, ItemQty varchar(100)) insert into inputTable(id, ItemQty) values (1, 'a,b,c'), (2, 'x,y'), (3, 'l,m,n,o,p'), (4, 'a,b'), (5, 'm') 我编写的存储过程如下所示: ALTER PROCEDURE [dbo].[dynamic_tbl]
作为参数:
create table inputTable (id int, ItemQty varchar(100))
insert into inputTable(id, ItemQty)
values (1, 'a,b,c'), (2, 'x,y'), (3, 'l,m,n,o,p'),
(4, 'a,b'), (5, 'm')
我编写的存储过程如下所示:
ALTER PROCEDURE [dbo].[dynamic_tbl]
(@tablename VARCHAR(50))
AS
BEGIN
/* To get the maximum value of ItemQty with comma's [IN THIS CASE IT IS 5 ] */
DECLARE @ColumnCount int
DECLARE @rowcount TABLE (Value int);
INSERT INTO @rowcount
EXEC('SELECT MAX(len(ITEMQTY) - len(replace(ITEMQTY, '','', '''')) +1) from '+@tablename);
SELECT @ColumnCount = Value FROM @rowcount;
DECLARE @ColumnName NVARCHAR(10)='qty_'
DECLARE @count INT = 0
IF (@ColumnCount > 0)
BEGIN
SET @count = @count + 1;
WHILE (@ColumnCount >= @count)
BEGIN
SET @ColumnName = 'qty_'+CONVERT(varchar(2),@count)
EXEC ('ALTER TABLE '+@tablename+' ADD ['+@ColumnName +'] varchar(20)')
DECLARE @myvar AS VARCHAR(MAX)
--set @myvar='update '+@tablename+' set '+@ColumnName +' =itemQty'
/* HERE ACTUALLY I AM GETTING PROBLEM, BECAUSE I WANT TO PARSE VALUES IN THE RESPECTIVE COLUMNS. */
EXEC(@myvar)
/* HERE, I wish to write the Actual update statement DYNAMICALLY*/
EXEC ('UPDATE '+@tablename+' set'+@ColumnName+'= ' )
SET @count = @count + 1;
END
END
END
我的输入和输出(期望的输出应如下图所示)
输出:
declare @myvar as varchar(max)
SET @MYVAR= 'update '+@tablename+ 'set' +@ColumnName+'=case when '+@count+' = 1 then itemQty else end'
exec(@myvar)
以动态方式将类似内容添加到代码中
declare @myvar as varchar(max)
SET @MYVAR= 'update '+@tablename+ 'set' +@ColumnName+'=case when '+@count+' = 1 then itemQty else end'
exec(@myvar)
请检查以下SQL Select语句
;with cte as (
select
i.id, i.ItemQty, s.id as rn, s.val
from inputTable as i
cross apply dbo.Split(ItemQty,',') as s
)
select
id, ItemQty,
max(qty1) qty1,
max(qty2) qty2,
max(qty3) qty3,
max(qty4) qty4,
max(qty5) qty5
from (
select
id,
ItemQty,
case when rn = 1 then val else null end as qty1,
case when rn = 2 then val else null end as qty2,
case when rn = 3 then val else null end as qty3,
case when rn = 4 then val else null end as qty4,
case when rn = 5 then val else null end as qty5
from cte
) t
group by id, ItemQty
结果如下
请注意,对于此解决方案,您需要一个。
检查可用于拆分字符串值的引用用户定义函数。
尽管您可以使用SQL Server 2016或更高版本的数据库平台,但我更喜欢使用自己的拆分函数,因为该函数也会返回拆分字符串片段的顺序
我希望它能有所帮助,变体,其中ItemQty
只包含一个符号'a,b,c'
ALTER PROCEDURE [dbo].[dynamic_tbl] (@tablename varchar(50))
AS
CREATE TABLE #inputTable(id int,ItemQty varchar(100))
-- insert all the data into temp table
DECLARE @copyScript varchar(MAX)
SET @copyScript='SELECT id,ItemQty FROM '+@tablename
INSERT #inputTable(id,ItemQty)
EXEC(@copyScript)
-- add columns and update data in #inputTable
DECLARE @maxColNum int
SET @maxColNum=(SELECT (MAX(LEN(ItemQty))+1)/2 FROM #inputTable)
DECLARE @curColNum int
SET @curColNum=1
DECLARE @updateScript varchar(MAX)
DECLARE @alterScript varchar(MAX)
WHILE @curColNum<=@maxColNum
BEGIN
-- add new column
SET @alterScript='ALTER TABLE '+@tablename+' ADD qty'+CAST(@curColNum AS varchar(5))+' varchar(100)'
--PRINT @alterScript
EXEC(@alterScript)
-- update data in new column
SET @updateScript='UPDATE i
SET
qty'+CAST(@curColNum AS varchar(5))+'=q.word
FROM '+@tablename+' i
JOIN
(
SELECT id,SUBSTRING(ItemQty,'+CAST((@curColNum-1)*2+1 AS varchar(5))+',1) word
FROM #inputTable
WHERE LEN(ItemQty)+1>='+CAST(@curColNum*2 AS varchar(5))+'
) q
ON i.ID=q.ID'
--PRINT @updateScript
EXEC(@updateScript)
SET @curColNum=@curColNum+1
END
DROP TABLE #inputTable
GO
-- test
EXEC dynamic_tbl 'inputTable'
-- show result
SELECT *
FROM inputTable
如果执行以下操作,可以将其作为脚本进行测试
--ALTER PROCEDURE [dbo].[dynamic_tbl] (@tablename varchar(50))
--AS
DECLARE @tablename varchar(50)='inputTable'
...
您好,谢谢您的时间,但我需要动态的方式,您可以完成它的代码,并向我展示输出。我不想使用分割函数,以及我不熟悉的xml路径,所以我希望它是可能的更新与一些动态循环您可以做分割使用一个WHILE循环在自定义项。请检查一下,您肯定可以找到其他T-SQL开发人员创建的许多SQL拆分函数。我认为有了#word,解决方案将更加简短和清晰。递归CTE只有一个额外的查询-这是一个一般性的区别。如果输入表有一个,bb,ccc,那么它应该在相应的列中将其作为bb ccc分开,但是如果使用第一个带#字的varian。此变体只能与“a、b、c”一起使用。