插入多个拆分的字符串列以将行分隔到sql表中

插入多个拆分的字符串列以将行分隔到sql表中,sql,sql-server,sql-server-2008,sql-server-2008-r2,Sql,Sql Server,Sql Server 2008,Sql Server 2008 R2,我有一张如下所示的表格 是否可以将上述表格数据插入到单独的行中的表格中 我尝试在每列上使用split函数,并将每列结果存储在临时表中。我不知道如何插入到新表中,根据id组合所有这些行和列。任何帮助或建议都会有所帮助 试试这个答案。希望这对你有帮助 DECLARE @Table TABLE(ID INT, NAME VARCHAR(10),TITLE VARCHAR(10)) INSERT INTO @Table VALUES (1,';a;b;c',';12;13;14') DECLARE @

我有一张如下所示的表格

是否可以将上述表格数据插入到单独的行中的表格中


我尝试在每列上使用split函数,并将每列结果存储在临时表中。我不知道如何插入到新表中,根据id组合所有这些行和列。任何帮助或建议都会有所帮助

试试这个答案。希望这对你有帮助

DECLARE @Table TABLE(ID INT, NAME VARCHAR(10),TITLE VARCHAR(10))
INSERT INTO @Table VALUES (1,';a;b;c',';12;13;14')

DECLARE @ID INT=1

SELECT @ID ID,Items,ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) RN1 INTO #T1 FROM dbo.split((SELECT NAME FROM @Table WHERE id=@ID),';')
SELECT @ID ID,Items,ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) RN2 INTO #T2 FROM dbo.split((SELECT TITLE FROM @Table WHERE id=@ID),';')

SELECT T1.ID,T1.Items NAME,T2.Items TITLE
FROM #T1 T1 INNER JOIN #T2 T2 ON T1.RN1=T2.RN2 

DROP TABLE #T1
DROP TABLE #T2
如果需要所有值,只需尝试WHILE之类的循环方法

这是split函数,我用来拆分字符串:

CREATE FUNCTION [dbo].[Split]
(@String VARCHAR (max), @Delimiter CHAR (1))
RETURNS 
    @temptable TABLE (
        [items] VARCHAR (max) COLLATE SQL_Latin1_General_CP1_CI_AS NULL)
AS
begin        
    declare @idx int        
    declare @slice varchar(max)        

    select @idx = 1        
        if len(@String)<1 or @String is null  return        

    while @idx!= 0        
    begin        
        set @idx = charindex(@Delimiter,@String)        
        if @idx!=0        
            set @slice = left(@String,@idx - 1)        
        else        
            set @slice = @String        

        if(len(@slice)>0)   
            insert into @temptable(Items) values(@slice)        

        set @String = right(@String,len(@String) - @idx)        
        if len(@String) = 0 break        
    end    
return        
end

试试下面的方法。。这将节省时间和内存也

此T-SQL块依赖于dbo.SplitString函数。。 T1是我的源表T2是我的目标表

这是dbo.SplitString


您可以通过编写一个表值函数来实现这一点,该函数将根据您的需求分割字符串。一旦创建了这个对象,就可以使用第二个代码段中的T-SQL来获取最终所需的表

此表值函数的定义如下所示。只需将其复制并粘贴到SSMS中,然后针对您的数据库运行它

拆分字符串函数

下面是另一种借助XML节点的CTE方法

不需要创建任何函数

WITH cte AS (
     SELECT ID,
            split.a.value('.', 'NVARCHAR(MAX)') [name],
            ROW_NUMBER() OVER(ORDER BY ( SELECT 1)) RN
     FROM
     (
         SELECT ID,
                CAST('<A>'+REPLACE(name, ';', '</A><A>')+'</A>' AS XML) AS [name]
         FROM <table_name>
     ) a
     CROSS APPLY name.nodes('/A') AS split(a)),
     CTE1 AS (
     SELECT ID,
            split.a.value('.', 'NVARCHAR(MAX)') [title],
            ROW_NUMBER() OVER(ORDER BY ( SELECT 1 )) RN
     FROM
     (
         SELECT ID,
                CAST('<A>'+REPLACE(title, ';', '</A><A>')+'</A>' AS XML) AS [title]
         FROM <table_name>
     ) aa
     CROSS APPLY title.nodes('/A') AS split(a))
     SELECT C.ID, C.name, C1.title FROM CTE C
          JOIN CTE1 C1 ON C1.RN = C.RN
     WHERE C.name != '' AND C1.title != '';

我不同意Dinesh脚本,因为它基于RBAR

我有一个非常类似的拆分函数,它还返回行号和项目

因此,请将我的脚本与其他示例数据一起测试

DECLARE @Table TABLE(ID INT, NAME VARCHAR(10),TITLE VARCHAR(10))
INSERT INTO @Table VALUES (1,',a,b,c',',12,13,14')

SELECT id
    ,t.RowVal
    ,a.RowVal
FROM (
    SELECT t.id
        ,a.RowNum
        ,a.RowVal
        ,t.TITLE
    FROM @Table t
    CROSS APPLY (
        SELECT *
        FROM dbo.FN_SPLIT_VALUE(t.NAME)
        ) a
    ) t
CROSS APPLY (
    SELECT *
    FROM dbo.FN_SPLIT_VALUE(t.TITLE)
    WHERE t.RowNum = RowNum
    ) a
WHERE t.RowVal <> ''

看看我的答案,希望它能帮助你。谢谢你的帮助。我试过剧本。我收到错误消息说“无效列名”项。列是什么,从拆分函数返回。如果你面临同样的问题,使用我建议你的功能。它工作得很好!非常感谢你。我的分割函数返回项目,我将项目改为项目,效果很好。我的答案有问题吗?没有问题。但当我在拥有34573行的表上实现该解决方案时,它断开了数据库并重新启动了数据库。这将导致中途停止拆分过程。我想我们可以选择多个答案。我没意识到这会删除你的答案。很抱歉
DECLARE @c_s AS CURSOR;
DECLARE @id INT;
DECLARE @name VARCHAR(1000);
DECLARE @value VARCHAR(1000);

SET @c_s = CURSOR FOR SELECT * FROM T1; 
OPEN @c_s;
FETCH @c_s INTO @id, @name, @value

WHILE @@FETCH_STATUS = 0
BEGIN
    INSERT INTO T2
    SELECT @id
        , a.Value NAME
        , b.value value
    FROM dbo.SplitString(@name, ';') a
    INNER JOIN dbo.SplitString(@value, ';') b
        ON a.OrdinalPosition = b.OrdinalPosition

  FETCH NEXT FROM @c_s INTO @id, @name, @value
END
CREATE FUNCTION [dbo].[SplitString](@givenString VARCHAR(8000) , @separator VARCHAR(100))
RETURNS TABLE AS
RETURN (
        WITH data([start], [end]) AS (
                SELECT 0 AS [start]
                    , CHARINDEX(@separator, @givenString) AS [end]
                UNION ALL
                SELECT [end] + 1
                    , CHARINDEX(@separator, @givenString, [end] + 1)
                FROM data
                WHERE [end] > 0
                )
        SELECT ROW_NUMBER() OVER (
                ORDER BY OrdinalPosition
                ) OrdinalPosition
            , RTRIM(LTRIM(Value)) Value
        FROM (
            SELECT ROW_NUMBER() OVER (
                    ORDER BY [start]
                    ) OrdinalPosition
                , SUBSTRING(@givenString, [start], COALESCE(NULLIF([end], 0), len(@givenString) + 1) - [start]) Value
            FROM data
            ) r
        WHERE RTRIM(Value) <> ''
            AND Value IS NOT NULL
        )
-- =============================================
-- Author:      B Vidhya
-- Create date: Nov 7, 2017
-- Description: Splits a string and returns a table
-- =============================================
CREATE FUNCTION [dbo].[SplitAString]
(    
      @string NVARCHAR(MAX),
      @delimiter CHAR(1)
)
RETURNS @splitTable TABLE (
      ItemNumber INT IDENTITY(1,1),
      Item NVARCHAR(1000)
)
AS
BEGIN
      DECLARE @startIndex INT,@endIndex INT

      SET @startIndex = 1
      IF SUBSTRING(@string, LEN(@string) - 1, LEN(@string)) <> @delimiter
      BEGIN
            SET @string = @string + @delimiter
      END

      WHILE CHARINDEX(@delimiter, @string) > 0
      BEGIN
            SET @endIndex = CHARINDEX(@delimiter, @string)

            INSERT INTO @splitTable(Item)
            SELECT SUBSTRING(@string, @startIndex, @endIndex - 1)

            SET @string = SUBSTRING(@string, @endIndex + 1, LEN(@string))
      END

      RETURN
END

GO
DECLARE @myTable TABLE
(Id    INT,
 Name  VARCHAR(5000),
 Title VARCHAR(5000)
);

DECLARE @lastId INT= 0, @id INT, @name VARCHAR(5000), @title VARCHAR(5000);

--for each record in table perform splitting and insertion in new table
WHILE EXISTS
(
    SELECT 1
    FROM StackOverFlowTable1 soft
    WHERE Id > @lastId
)
    BEGIN
        SELECT TOP (1) @id = Id,
                       @name = Name,
                       @title = Title
        FROM StackOverFlowTable1 soft
        WHERE Id > @lastId
        ORDER BY Id;
        SET @lastId = @id;
        INSERT INTO @myTable
        (Id,
         Name,
         Title
        )
               SELECT @id,
                      ss1.Item,
                      ss2.Item
               FROM dbo.SplitString(@name, ';') ss1
                    INNER JOIN dbo.SplitString(@title, ';') ss2 ON ss1.ItemNumber = ss2.ItemNumber
               WHERE ss1.Item <> ''
                     AND ss2.Item <> '';
    END;

SELECT * FROM @myTable;
WITH cte AS (
     SELECT ID,
            split.a.value('.', 'NVARCHAR(MAX)') [name],
            ROW_NUMBER() OVER(ORDER BY ( SELECT 1)) RN
     FROM
     (
         SELECT ID,
                CAST('<A>'+REPLACE(name, ';', '</A><A>')+'</A>' AS XML) AS [name]
         FROM <table_name>
     ) a
     CROSS APPLY name.nodes('/A') AS split(a)),
     CTE1 AS (
     SELECT ID,
            split.a.value('.', 'NVARCHAR(MAX)') [title],
            ROW_NUMBER() OVER(ORDER BY ( SELECT 1 )) RN
     FROM
     (
         SELECT ID,
                CAST('<A>'+REPLACE(title, ';', '</A><A>')+'</A>' AS XML) AS [title]
         FROM <table_name>
     ) aa
     CROSS APPLY title.nodes('/A') AS split(a))
     SELECT C.ID, C.name, C1.title FROM CTE C
          JOIN CTE1 C1 ON C1.RN = C.RN
     WHERE C.name != '' AND C1.title != '';
ID  name title
1   a    12
1   b    13
1   s    45
2   c    67
2   f    56
2   u    34
3   l    90
3   k    70
3   m    60
DECLARE @Table TABLE(ID INT, NAME VARCHAR(10),TITLE VARCHAR(10))
INSERT INTO @Table VALUES (1,',a,b,c',',12,13,14')

SELECT id
    ,t.RowVal
    ,a.RowVal
FROM (
    SELECT t.id
        ,a.RowNum
        ,a.RowVal
        ,t.TITLE
    FROM @Table t
    CROSS APPLY (
        SELECT *
        FROM dbo.FN_SPLIT_VALUE(t.NAME)
        ) a
    ) t
CROSS APPLY (
    SELECT *
    FROM dbo.FN_SPLIT_VALUE(t.TITLE)
    WHERE t.RowNum = RowNum
    ) a
WHERE t.RowVal <> ''