动态添加列,并在相应列中添加Later Parse值

时间:2017-11-16 08:38:20

标签: sql-server sql-server-2008

我有一个接受<TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textColor="#000" android:background="#ffea00" android:textSize="20sp" android:text="পরিবার" android:paddingLeft="5dp" /> 参数的SP,我的Inputtable如代码所示

Inputtable

和我写的SP如下所示

`create table inputTable ( id int,ItemQty varchar(100))
insert into inputTable(id, ItemQty) values(1,'a,b,c')
insert into inputTable(id, ItemQty) values(2,'x,y')
insert into inputTable(id, ItemQty) values(3,'l,m,n,o,p')
insert into inputTable(id, ItemQty) values(4,'a,b')
insert into inputTable(id, ItemQty) values(5,'m')`

我的表是:enter image description here

步骤1)我想将列动态添加到输入表格`ALTER PROCEDURE [dbo].[Column_Dynamics] (@tablename varchar(50)) AS BEGIN ----- declare @maxcount as int set @maxcount='select MAX(len(ITEMQTY) - len(replace(ITEMQTY, '','', '''')) +1) from '+@tablename exec('select MAX(len(ITEMQTY) - len(replace(ITEMQTY, '','', '''')) +1) from '+@tablename) print @maxcount exec @maxcount print @maxcount declare @var varchar(100) IF EXISTS(SELECT * FROM sys.columns WHERE object_id = Object_id(@tablename)) set @var='alter table '+ @tablename +' ADD column QTY1' exec(@var) select * from @tablename select max(len(ItemQty))-max(len(replace(ItemQty, ',', ''))-1) from inputtable END` ,因为ItemQty列的最大计数为5,将逗号视为分隔符,如图1所示

enter image description here

**步骤2)**在各列中解析值(通过考虑分隔符逗号(QTY1,QTY2,QTY3,QTY4,QTY5)。如图2所示

enter image description here

后来的SP:我到了这里,但没有得到第二步,就是更新相应列中的Parse值。

,

3 个答案:

答案 0 :(得分:1)

根据您的要求

,根据列长度动态更改给定表的过程
Alter PROCEDURE [dbo].[Column_Dynamics] (@tablename varchar(50))
AS
BEGIN
drop table ##temp
declare @query1 varchar(max)
exec ( '
create table ##temp (id int identity,columnsl varchar(100))
declare @maxcount as int
set @maxcount = (select MAX(len(ITEMQTY) - len(replace(ITEMQTY, '','', '''')) +1) from '+@tablename+') 

declare @count int = 1
while (@count <= @maxcount)
begin
declare @colvar nvarchar(100)= ''QTY''
set @colvar = concat(@colvar,@count)
set @count = @count + 1

insert into ##temp select @colvar
end
')

declare @tempstart int = 1
declare @templast int = (select count(*) from ##temp)
declare @updatecol varchar(100) = ''

while (@tempstart <= @templast)
Begin
set @updatecol = (select columnsl from ##temp where id = @tempstart)
exec ('alter table '+@tablename+' Add '+@updatecol+' varchar(100) ')
set @tempstart = @tempstart + 1
end    
End

inputTable的输出:

id  ItemQty    QTY1   QTY2     QTY3   QTY4    QTY5
1   a,b,c      NULL   NULL    NULL    NULL     NULL
2   x,y        NULL   NULL    NULL    NULL    NULL
3   l,m,n,o,p  NULL   NULL    NULL    NULL    NULL
4   a,b        NULL   NULL    NULL    NULL    NULL
5   m          NULL   NULL    NULL    NULL    NULL

可能不是最好的方式,但有效。

修改

修改上述程序以执行这两个操作,请使用以下程序

Alter PROCEDURE [dbo].[Column_Dynamics] (@tablename varchar(50))
AS
BEGIN
--  declare @tablename varchar(100) = 'inputTable'
drop table #temp if object_id('temp..#temp') is not null drop table #temp
declare @query1 varchar(max)
create table #temp (id int identity,columnsl varchar(100))
exec ( '
declare @maxcount as int
set @maxcount = (select MAX(len(ITEMQTY) - len(replace(ITEMQTY, '','', '''')) +1) from '+@tablename+') 

declare @count int = 1
while (@count <= @maxcount)
begin
declare @colvar nvarchar(100)= ''QTY''
set @colvar = concat(@colvar,@count)
set @count = @count + 1

insert into #temp
select @colvar

end

')
declare @tempstart int = 1
declare @templast int = (select count(*) from #temp)
declare @updatecol varchar(100) = ''
declare @itemqty varchar(100)

while (@tempstart <= @templast)
Begin
set @updatecol = (select columnsl from #temp where id = @tempstart)
exec ('alter table '+@tablename+' Add '+@updatecol+' varchar(100) ')

set @tempstart = @tempstart + 1
end

declare @sysvar table (id int identity,cols varchar(100))
insert into @sysvar select sys.columns.name AS ColumnName FROM sys.columns JOIN sys.tables ON sys.columns.object_id = sys.tables.object_id  WHERE sys.tables.name = 'inputTable'

declare @finvar table (id int identity,cols varchar(100))
insert into @finvar select cols from @sysvar where id not in (1,2)

declare @cat int = 1  declare @dog int = (select max(id) from inputTable)

while (@cat <= @dog)
begin
drop table #tab2
if object_id('temp..#tab2') is not null drop table #tab2
create table #tab2 (id int identity,fnvalues varchar(100))

set @itemqty = (select itemqty from inputTable where id = @cat)
insert into #tab2 select item from [dbo].[fnSplit](@itemQty,',')  

declare @cn int = 1 
declare @max int = (select max(id) from #tab2)
declare @sql nvarchar (1000);

while (@cn <= @max)
begin
declare @upcol varchar(100) = (select fnvalues from #tab2 where id = @cn)
declare @plscol varchar(100) = (select cols from @finvar where id = @cn)

set @sql = N'update '+@tablename+' set ' + @plscol + '= '''+@upcol+''' where id = '''+cast(@cat as varchar(10))+''' ';
select @sql
exec sp_executesql @sql;

set @cn = @cn + 1

end
set @cat = @cat + 1
End

End

输出:

id  ItemQty    QTY1 QTY2 QTY3   QTY4    QTY5
1   a,b,c       a   b     c      NULL   NULL
2   x,y         x   y     NULL   NULL   NULL
3   l,m,n,o,p   l   m     n      o      p
4   a,b         a   b     NULL   NULL   NULL
5   m           m   NULL  NULL   NULL   NULL

没有优化查询,但工作正常。

答案 1 :(得分:0)

但是,如果您知道的最大数量是逗号分隔格式,那么您可以使用xml节点方法将它们分隔为columnsQTY1 .. 。QTY5

SELECT DISTINCT ID, ITEMQTY,
       a.value('/A[1]', 'VARCHAR(MAX)') as QTY1,
       a.value('/A[2]', 'VARCHAR(MAX)') as QTY2,
       a.value('/A[3]', 'VARCHAR(MAX)') as QTY3,
       a.value('/A[4]', 'VARCHAR(MAX)') as QTY4,
       a.value('/A[5]', 'VARCHAR(MAX)') as QTY5
FROM
(
    SELECT ID, ITEMQTY,
           CAST('<A>'+REPLACE(ITEMQTY, ',', '</A><A>')+'</A>' AS XML) AS ITEMQTY1
    FROM inputTable
) A
CROSS APPLY ITEMQTY1.nodes('/A') AS split(a); 

结果:

ID  ITEMQTY   QTY1  QTY2    QTY3    QTY4    QTY5
1   a,b,c     a     b       c       NULL    NULL
2   x,y       x     y       NULL    NULL    NULL
3   l,m,n,o,p l     m       n       o       p
4   a,b       a     b       NULL    NULL    NULL
5   m         m    NULL     NULL    NULL    NULL

稍后,您可以使用nullcoalesce()函数替换isnull() ''

答案 2 :(得分:0)

使用此

首先创建一个功能

CREATE FUNCTION [dbo].[fn_split](
@str VARCHAR(MAX),
@delimiter CHAR(1)
)
RETURNS @returnTable TABLE (idx INT PRIMARY KEY IDENTITY, item VARCHAR(8000))
AS
BEGIN
DECLARE @pos INT
SELECT @str = @str + @delimiter
WHILE LEN(@str) > 0 
    BEGIN
        SELECT @pos = CHARINDEX(@delimiter,@str)
        IF @pos = 1
            INSERT @returnTable (item)
                VALUES (NULL)
        ELSE
            INSERT @returnTable (item)
                VALUES (SUBSTRING(@str, 1, @pos-1))
        SELECT @str = SUBSTRING(@str, @pos+1, LEN(@str)-@pos)       
    END
RETURN
END
GO

并使用这样的功能

Declare @test TABLE (
ID VARCHAR(200),
Data VARCHAR(200)
)

insert into @test 
(ID, Data)
Values
(1,'a,b,c')


insert into @test 
(ID, Data )
values(2,'x,y')

insert into @test 
(ID, Data )
values(3,'l,m,n,o,p')

insert into @test 
(ID, Data )
values(4,'a,b')

insert into @test 
(ID, Data )
values(5,'m')

select ID,data AS ItemQty,
ISNULL((select item from fn_split(Data,',') where idx in (1)),'') as QTY1 ,
ISNULL((select item from fn_split(Data,',') where idx in (2)),'') as QTY2,
ISNULL((select item from fn_split(Data,',') where idx in (3)),'') as QTY3,
ISNULL((select item from fn_split(Data,',') where idx in (4)),'') as QTY5 ,
ISNULL((select item from fn_split(Data,',') where idx in (5)),'') as QTY5
 from @test

输出与图像相同

enter image description here

而不是使用

insert into @test 
(ID, Data)
Values
(1,'a,b,c')

你也可以这样点赞

insert into @test 
    (ID, Data)
    Values
    (Select Column1, Column2 From YourTable)