我有一个存储过程接受InputTable
作为参数:
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)
答案 0 :(得分:0)
请检查以下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 string split function。 检查引用的用户定义函数,该函数可用于拆分字符串值。 虽然如果您有SQL Server 2016或更高版本的数据库平台,可以使用STRING_SPLIT function,但是我更喜欢使用自己的split函数,因为该函数也会返回分割字符串片段的顺序。
我希望它有所帮助,
答案 1 :(得分:0)
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
下一个变体可以包含'a,bb,ccc'
等字符串。
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)
-- get all the words for each ID and put them into #words
;WITH wordsCTE AS(
SELECT
id,
ItemQty,
1 StartPosition,
CASE WHEN CHARINDEX(',',ItemQty)>0 THEN CHARINDEX(',',ItemQty) ELSE LEN(ItemQty)+1 END CommaPos,
1 WordNum
FROM #inputTable
UNION ALL
SELECT
i.id,
i.ItemQty,
c.CommaPos+1 StartPosition,
CASE WHEN CHARINDEX(',',c.ItemQty,c.CommaPos+1)>0 THEN CHARINDEX(',',c.ItemQty,c.CommaPos+1) ELSE LEN(c.ItemQty)+1 END CommaPos,
c.WordNum+1
FROM #inputTable i
JOIN wordsCTE c ON i.id=c.id
WHERE c.CommaPos<LEN(c.ItemQty)
)
--SELECT *,SUBSTRING(ItemQty,StartPosition,CommaPos-StartPosition) word
SELECT id,SUBSTRING(ItemQty,StartPosition,CommaPos-StartPosition) word,WordNum INTO #words
FROM wordsCTE
--ORDER BY id,word
-- add columns and update data in #inputTable
DECLARE @maxColNum int
SET @maxColNum=(SELECT MAX(WordNum) FROM #words)
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 *
FROM #words
WHERE WordNum='+CAST(@curColNum AS varchar(5))+'
) q
ON i.ID=q.ID'
--PRINT @updateScript
EXEC(@updateScript)
SET @curColNum=@curColNum+1
END
DROP TABLE #words
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'
...