代码之家  ›  专栏  ›  技术社区  ›  Darknight

将两个域合并为一个域,只包含新项

  •  1
  • Darknight  · 技术社区  · 15 年前

    我有两个表,都包含“管道分隔值”

    例如:

    表1:

     DataField_A
    
     item 1|item 2|item 3|etc.....
    

    表2:

     DataField_A
    
     item 7|item 5|item 3|etc.....
    

    我需要将表2合并到表1中,以便表2包含两个表中的所有项。

    如果表1中不存在表1,那么按语法顺序执行这项操作很简单,只需循环遍历表2中的每个项并添加到表1中。

    如何在SQL中以存储过程的形式执行此操作?

    1 回复  |  直到 15 年前
        1
  •  1
  •   Joe Stefanelli    15 年前

    我使用了一个解析函数(我使用的示例来自 here )分析表1中的字符串。然后我用这个函数 CTE 查找表2中缺少的元素并合并数据。

    /* Helper function to parse delimited string */
    CREATE FUNCTION [dbo].[fnParseStringTSQL] (@string NVARCHAR(MAX),@separator NCHAR(1))
    RETURNS @parsedString TABLE (string NVARCHAR(MAX))
    AS 
    BEGIN
       DECLARE @position int
       SET @position = 1
       SET @string = @string + @separator
       WHILE charindex(@separator,@string,@position) <> 0
          BEGIN
             INSERT into @parsedString
             SELECT substring(@string, @position, charindex(@separator,@string,@position) - @position)
             SET @position = charindex(@separator,@string,@position) + 1
          END
         RETURN
    END
    go
    
    /* Set up some sample data */
    declare @Table1 table (
        id int,
        DataField_1A varchar(500)
    )
    
    declare @Table2 table (
        id int,
        DataField_2A varchar(500)
    )
    
    insert into @Table1
        (id, DataField_1A)
        select 1, 'item 1|item 2|item 3'
        union
        select 2, 'item A|item B|item C|item D|item Z'
    
    insert into @Table2
        (id, DataField_2A)
        select 1, 'item 7|item 5|item 3'
        union
        select 2, 'item A|item Y|item Z'
    
    /* data before the update */
    select * from @Table2
    
    /* boolean to ensure loop executes at least once */
    declare @FirstLoop bit
    set @FirstLoop = 1
    
    /* Do the updates */
    while (@FirstLoop = 1 or @@ROWCOUNT <> 0) begin 
        set @FirstLoop = 0
    
        ;with cteMissingItems as (
        select t2.id, p.string
            from @Table2 t2
                inner join @Table1 t1
                    on t2.id = t1.id
                cross apply dbo.fnParseStringTSQL(t1.DataField_1A,'|') p
            where charindex(p.string, t2.DataField_2A) = 0
        )
        update t2
            set t2.DataField_2A = t2.DataField_2A + '|' + mi.string
            from @Table2 t2
                inner join cteMissingItems mi
                    on t2.id = mi.id
    end /* while */
    
    /* Prove the update worked */
    select * from @Table2
    
    /* Clean up */
    drop function dbo.fnParseStringTSQL
    
    推荐文章