学而实习之 不亦乐乎

Sql Server数据拆分:将一行数据拆分成多条记录

2019-01-20 11:21:19

假设在一个表中,name列中有许多人名,人名间以逗号分隔,现在需要将name字段中的名字拆分开,每个名字成为一条记录。

一、创建表
创建表如下:
CREATE TABLE [dbo].[tb_0001](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [name] [nvarchar](100) NOT NULL
) ON [PRIMARY]
GO

添加数据
INSERT INTO [dbo].[tb_0001]([name])VALUES('张三')
INSERT INTO [dbo].[tb_0001]([name])VALUES('李四,王五')
INSERT INTO [dbo].[tb_0001]([name])VALUES('赵六,小七,大八,憨九')
INSERT INTO [dbo].[tb_0001]([name])VALUES('老十,老十一,老十二')
INSERT INTO [dbo].[tb_0001]([name])VALUES('老十四,老十五,老十六')

二、实现方法
方法1:
1.首先需要自定义一个切分函数
CREATE FUNCTION [dbo].[MY_SPLIT](@sourceStr NVARCHAR(MAX),@separator NVARCHAR(100))    
RETURNS  @tmp TABLE(        
    SPLIT_ID INT IDENTITY PRIMARY KEY,      
    SPLIT_STR NVARCHAR(MAX)    
)    
AS   
BEGIN   
    DECLARE @short_str NVARCHAR(MAX),@split_str_length int,@split_str_Position_Begin int
    SET @split_str_length = LEN(@separator) 
    SET @sourceStr=REPLACE(REPLACE(@sourceStr,CHAR(10),''),CHAR(13),'')
    IF CHARINDEX(@separator,@sourceStr)=1 
         SET @sourceStr=STUFF(@sourceStr,1,@split_str_length,'')
    IF CHARINDEX(@separator,@sourceStr)=0
        INSERT INTO @tmp SELECT @sourceStr 
    ELSE
        BEGIN
            WHILE 1>0    
                BEGIN   
                    SET @split_str_Position_Begin = CHARINDEX(@separator,@sourceStr)
                    SET @short_str=LEFT(@sourceStr,@split_str_Position_Begin-1) 
                    IF @short_str<>'' INSERT INTO @tmp SELECT @short_str  
                    SET @sourceStr=STUFF(@sourceStr,1,@split_str_Position_Begin+@split_str_length-1,'')
                    SET @split_str_Position_Begin = CHARINDEX(@separator,@sourceStr)
                    IF @split_str_Position_Begin=0 
                    BEGIN
                        IF LTRIM(@sourceStr)<>''
                            INSERT INTO @tmp SELECT @sourceStr 
                        BREAK
                    END
                END           
        END
    RETURN     
END

2,然后执行下面的SQL语句
SELECT SPLIT_ID,SPLIT_STR
FROM  dbo.tb_0001 AS t1 CROSS apply dbo.MY_SPLIT(t1.name,',') AS t2

可以看到字段完成拆分,如下图:

方法2:
SqlServer支持XML数据格式,可以将name字段,转换成XML格式,其原理与方法一的不同。
SELECT 
    tb01.id
   ,tb02.VALUE 
FROM
    ( SELECT id,[value] = CONVERT(xml,'<root><v>' + REPLACE(name, ',', '</v><v>') + '</v></root>') FROM dbo.tb_0001 ) AS tb01  
    OUTER APPLY
    ( SELECT VALUE = N.v.value('.', 'varchar(100)') FROM tb01.[value].nodes('/root/v') N(v) ) AS tb02