首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > SQL Server >

一个存储过程的有关问题 求指点

2013-06-26 
一个存储过程的问题 求指点描述: 假设有一张表,8个字段F1, F2, F3, F4, F5, F6, F7, F8。其中F1是表的自增

一个存储过程的问题 求指点
描述: 假设有一张表,8个字段F1, F2, F3, F4, F5, F6, F7, F8。其中F1是表的自增长的关键字,F2是手工输入的多个编号【都是数字】(有两种格式,用"、“分隔或用”-“分隔,如果用”、“分隔,表示并列关系,比如1、3,表示1和3;用”-“分隔,表示从什么到什么,比如1-3,表示,1,2,和3。当然编号数目最多6个),F3到F8默认都是空的.
 
实现的功能:就是读取每一行,然后把该行的F2的多个编号拆分出来,然后按次序填入F3到F8字段中。
 
   比如第一行是 F1 (1),  F2 (5, 7),则填入F3是5,F4是7,F6到F8继续留空
       第二行是 F1 (2),  F2 (5 - 7),则填入F3是5, F4是6,F5是7, F6到F8继续留空

目前做的T-SQL为:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:<Author,,Name>
-- Create date: <Create Date,,>
-- Description:<Description,,>
-- =============================================
ALTER PROCEDURE SplitData
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

declare @F1 INT
declare @F2 NVARCHAR(50)
declare @F3 TINYINT = NULL
declare @F4 TINYINT= NULL
declare @F5 TINYINT= NULL
declare @F6 TINYINT= NULL
declare @F7 TINYINT= NULL
declare @F8 TINYINT= NULL
declare @TAG NVARCHAR = NULL
declare @COUNT TINYINT = NULL


declare cursor1 cursor for
select F1,F2 from [DB0502].[dbo].[TB0502]  
open cursor1 
 
fetch next from cursor1 into @F1,@F2

while @@fetch_status=0 
begin

set @F3=SUBSTRING(@F2,1,1); 
set @TAG=SUBSTRING(@F2,2,1);  

IF @TAG='、'
BEGIN 
SET @F4 = SUBSTRING(@F2,3,1);
END

IF @TAG='-'
BEGIN 
SET @COUNT = SUBSTRING(@F2,3,1) - @F3; 
IF @COUNT = 5
BEGIN
SET @F4 = @F3+1;
SET @F5 = @F4+1;
SET @F6 = @F5+1;
SET @F7 = @F6+1;
SET @F8 = @F7+1;
END
IF @COUNT = 4
BEGIN
SET @F4 = @F3+1;
SET @F5 = @F4+1;
SET @F6 = @F5+1;
SET @F7 = @F6+1;
END
IF @COUNT = 3
BEGIN
SET @F4 = @F3+1;
SET @F5 = @F4+1;
SET @F6 = @F5+1;
END
IF @COUNT = 2
BEGIN
SET @F4 = @F3+1;
SET @F5 = @F4+1;
END
IF @COUNT = 1
BEGIN
SET @F4 = @F3+1;
END
END
UPDATE [DB0502].[dbo].[TB0502] SET F3=@F3,F4=@F4,F5=@F5,F6=@F6,F7=@F7,F8=@F8
where F1=@F1                           

fetch next from cursor1 into @F1,@F2 
end
close cursor1 
deallocate cursor1 
 
END
GO


目前只5个字段,红色部分写了5个判断,如果有更多的话,就要再加判断,
有没有更好的处理方式,跪求大神指点疑惑!


[解决办法]
使用动态语句进行拼接,Exec sp_executesql 
根据F2中的数量,动态的生成插入语句。最后执行语句就可以

[解决办法]
CREATE  FUNCTION GetColValue(@F2 NVARCHAR(50) )  
RETURNS NVARCHAR(100)
BEGIN
DECLARE @Lh NVARCHAR(50),@Lb NVARCHAR(50),@Ltmp NVARCHAR(50)
DECLARE @Pos INT ,@I INT
 
SELECT @Pos=CHARINDEX('-',@F2)
WHILE @Pos>0
BEGIN
SELECT @Lh=SUBSTRING(@F2,@Pos-1,1),@Lb=SUBSTRING(@F2,@Pos+1,1),@Ltmp=NULL
WHILE @Lh*1<=@Lb*1
SELECT @Ltmp=ISNULL(@Ltmp+'、','')+@Lh ,@Lh=ltrim(@Lh*1+1)

SELECT @F2=STUFF(@F2,@Pos-1,3,@Ltmp),@Pos=CHARINDEX('-',@F2)
END

SELECT @I=3,@F2=REPLACE(@F2,'、',',')+',',@Ltmp=''

WHILE @F2>''
BEGIN
SELECT @Ltmp=@Ltmp+ '[F'+Ltrim(@I)+']='+LEFT(@F2,CHARINDEX(',',@F2)-1)+',',@F2=RIGHT(@F2,LEN(@F2)-CHARINDEX(',',@F2))
SET @I=@I+1
END

RETURNSTUFF(@Ltmp,LEN(@Ltmp),1,'')
END

GO
exec MASTER.dbo.xp_execresultset 'SELECT ''UPDATE [TB0502] SET ''+dbo.GetColValue(F2)+'' WHERE [F1]=''+LTRIM(F1) FROM [TB0502]' ,'test'

GO
SELECT * FROM tb0502

--RESULT
/*F1          F2                                                 F3   F4   F5   F6   F7   F8   
----------- -------------------------------------------------- ---- ---- ---- ---- ---- ---- 
1           1、3                                                1    3    NULL NULL NULL NULL
2           2、4                                                2    4    NULL NULL NULL NULL
3           3、5                                                3    5    NULL NULL NULL NULL
4           1-3                                                1    2    3    NULL NULL NULL
5           2-4                                                2    3    4    NULL NULL NULL


6           3-5                                                3    4    5    NULL NULL NULL
7           3-8                                                3    4    5    6    7    8

(所影响的行数为 7 行)*/

[解决办法]


CREATE TABLE [dbo].[TB0502](
[F1] [int] IDENTITY(1,1) NOT NULL,
[F2] [nvarchar](50) NULL,
[F3] [tinyint] NULL,
[F4] [tinyint] NULL,
[F5] [tinyint] NULL,
[F6] [tinyint] NULL,
[F7] [tinyint] NULL,
[F8] [tinyint] NULL,
CONSTRAINT [PK_T0502] PRIMARY KEY CLUSTERED 
([F1] ASC))

INSERT INTO [TB0502]([F2],[F3],[F4],[F5],[F6],[F7],[F8])
  VALUES('1、3',null,null,null,null,null,null)
INSERT INTO [TB0502]([F2],[F3],[F4],[F5],[F6],[F7],[F8])
  VALUES('2、4',null,null,null,null,null,null)
INSERT INTO [TB0502]([F2],[F3],[F4],[F5],[F6],[F7],[F8])
  VALUES('3、5',null,null,null,null,null,null)
INSERT INTO [TB0502]([F2],[F3],[F4],[F5],[F6],[F7],[F8])
  VALUES('1-3',null,null,null,null,null,null)
INSERT INTO [TB0502]([F2],[F3],[F4],[F5],[F6],[F7],[F8])
  VALUES('2-4',null,null,null,null,null,null)
INSERT INTO [TB0502]([F2],[F3],[F4],[F5],[F6],[F7],[F8])
  VALUES('3-5',null,null,null,null,null,null)
INSERT INTO [TB0502]([F2],[F3],[F4],[F5],[F6],[F7],[F8])
  VALUES('3-8',null,null,null,null,null,null)


select F1,F2,F3,F4,F5,F6,F7,F8 from TB0502
/*
F1          F2              F3   F4   F5   F6   F7   F8
----------- -------------- ---- ---- ---- ---- ---- ----
1           1、3            NULL NULL NULL NULL NULL NULL
2           2、4            NULL NULL NULL NULL NULL NULL
3           3、5            NULL NULL NULL NULL NULL NULL
4           1-3             NULL NULL NULL NULL NULL NULL
5           2-4             NULL NULL NULL NULL NULL NULL
6           3-5             NULL NULL NULL NULL NULL NULL


7           3-8             NULL NULL NULL NULL NULL NULL

(7 row(s) affected)
*/


with t as
(select a.F1,
        substring(a.F2,b.number,charindex('、',a.F2+'、',b.number)-b.number) 'Fv'
 from TB0502 a, master.dbo.spt_values b
 where charindex('、',a.F2,1)>0 and 
 b.type='P' and b.number between 1 and len(a.F2)
 and substring('、'+a.F2,b.number,1)='、'
 union all
 select c.F1,d.number 'Fv'
 from TB0502 c, master.dbo.spt_values d
 where charindex('-',c.F2,1)>0 and d.type='P'
 and d.number between substring(c.F2,1,charindex('-',c.F2)-1) 
 and substring(c.F2,charindex('-',c.F2)+1,50)
),
j as
(select g.F1,g.F2,g.number,h.Fv
 from
 (select e.F1,e.F2,f.number
  from TB0502 e
  cross join master.dbo.spt_values f
  where f.type='P' and f.number between 3 and 8) g
 left join
 (select F1,Fv,
         row_number() over(partition by F1 order by Fv)+2 'rn'
  from t) h on g.F1=h.F1 and g.number=h.rn
)
update m
 set m.F3=n.[3], m.F4=n.[4], m.F5=n.[5],
     m.F6=n.[6], m.F7=n.[7], m.F8=n.[8]
 from TB0502 m
 inner join 
 (select F1,F2,[3],[4],[5],[6],[7],[8]
  from j
  pivot(max(Fv) for number in([3],[4],[5],[6],[7],[8])) k) n
 on m.F1=n.F1 and m.F2=n.F2


select F1,F2,F3,F4,F5,F6,F7,F8 from TB0502
/*
F1          F2              F3   F4   F5   F6   F7   F8
----------- -------------- ---- ---- ---- ---- ---- ----
1           1、3            1    3    NULL NULL NULL NULL
2           2、4            2    4    NULL NULL NULL NULL
3           3、5            3    5    NULL NULL NULL NULL
4           1-3             1    2    3    NULL NULL NULL
5           2-4             2    3    4    NULL NULL NULL
6           3-5             3    4    5    NULL NULL NULL


7           3-8             3    4    5    6    7    8

(7 row(s) affected)
*/

热点排行