循环遍历表数据并使用split

时间:2015-12-01 16:36:52

标签: sql sql-server tsql

我有两个表,我需要比较数据并更新/插入一个表记录。我想要做的是我需要从Table1中获取每条记录, 然后对split中的每个文本使用split函数,比较这两个表之间的dataelement字段。我们将Table2中的数据同步到类似于Table1。 请让我知道如何做到这一点。我可以使用光标或合并。这是方案

DataTable:

dataId    dataelement
1           Check
2           System
3           Balances
4           City
5           State
6           Zip
7           Other


Table1:

Id    reqId      dataelementValues
1       52       Check
2       52       City;State;System
3       52       Other

Table2:

elId  dataId   dataelement reqId Active
1      6          Zip        52    1
2      1          Check      52    1
3      4          city       52    1
4      5          State      52    1

结果应与表2中的比较相似

Table2:

elId  dataId   dataelement reqId Active
1      6          Zip        52    0 (Should be set to inactive as it exists in table2 but not in table1)
2      1          Check      52    1 (NO Updates as it exists in both the tables) 
3      4          city       52    1 (NO Updates as it exists in both the tables) 
4      5          State      52    1 (NO Updates as it exists in both the tables) 

5      2          System     52    1 (Get the dataid for system from datatable and insert in table2 as it exists in table1 but not in table2) 
6      7          Other      52    1 (Get the dataid for other  from datatable and insert in table2 as it exists in table1 but not in table2) 

这就是iam at,不知道如何在table2上设置非活动状态。

WHILE Exists(Select * from #Table1)      
     BEGIN            
            Select @currentId = Id, @dataValue = dataelementValues FROM #Table1 where rowID=(SELECT top 1 rowID from #Table1 order by rowID asc) 


           SET @pos = 0
           SET @len = 0
           WHILE CHARINDEX(';', @dataValue, @pos+1)>0
            BEGIN               
                SET @dataValueValue = SUBSTRING(@dataValue, @pos, CHARINDEX('|', @dataValue, @pos+1) - @pos)               
                SET @glbaDEId = (Select DataTable.dataId  from datatable where dataelement = @dataValue)                     

                IF NOT Exists (Select * from #Table2  Where DataElement=@dataValue)
                   BEGIN                   
                      --Insert into table2
                    END             

                 SET @pos = CHARINDEX('|', @dataValue, @pos+@len) +1
                END

           DELETE from #Table1 where rowID=(SELECT top 1 rowID from #Table1 order by rowID asc )   
      END

3 个答案:

答案 0 :(得分:1)

您可以尝试使用带有其他一些技巧的MERGE语句。

Merge Guide

-- Create a CTE that will split out the combined column and join to DataTable 
-- to get the dataId
;WITH cteTable1Split AS
(
    SELECT reqId, dt.* FROM
    (  
        SELECT 
            [dataelement] = y.i.value('(./text())[1]', 'nvarchar(4000)'),
            reqId
        FROM 
        ( 
            -- use xml to split column 
            -- http://sqlperformance.com/2012/07/t-sql-queries/split-strings
            SELECT x = CONVERT(XML, '<i>' 
                + REPLACE([dataelementValues], ';', '</i><i>') 
                + '</i>').query('.'),
                   reqId
            FROM Table1
        ) AS a CROSS APPLY x.nodes('i') AS y(i)
    ) a
    JOIN DataTable dt ON dt.[dataelement] = a.[dataelement]
)
-- Merge Table2 with the CTE
MERGE INTO Table2 AS Target
USING cteTable1Split AS Source 
ON Target.[dataelement] = Source.[dataelement]

-- If exists in Target (Table2) but not Source (CTE) then UPDATE Active flag
WHEN NOT MATCHED BY Source THEN
UPDATE SET ACTIVE = 0

-- If exists in Source (CTE) but not Target (Table2) then INSERT new record
WHEN NOT MATCHED BY TARGET THEN
INSERT ([dataId], [dataelement], [reqId], [Active]) 
VALUES (SOURCE.[dataId], SOURCE.[dataelement], SOURCE.[reqId], 1);

SQL Fiddle

答案 1 :(得分:0)

您没有提及是否可以控制这些表的结构,因此我将继续建议您重新设计Table1以规范化dataelementValues列

即代替:

Table1:

Id    reqId      dataelementValues
1       52       Check
2       52       City;State;System
3       52       Other

你应该存储这个:

Table1_New:

Id    reqId      dataelementValues
1       52       Check
2       52       City
2       52       State
2       52       System
3       52       Other

您可能还需要使用IDENTITY(1,1)规范在表格中使用新的代理主键列。

像这样存储您的数据是如何使用/设计关系数据库的。除了现在简化手头的问题之外,您可能会发现它在将来也会消除潜在的问题。

答案 2 :(得分:0)

这里的主要挑战是创建一个rowset,其中dataelementValues正确地拆分为单独的行。接受的答案清楚地显示了如何将source作为merge语句来实现更新和插入操作。

但是,还有其他方法可以创建拆分或规范化行集。

我个人更喜欢在这种特殊情况下使用xml的一种方式是like join。这利用了这样一个事实:您已经在DataTable中拥有了所需的单独行,而不是您需要的所有列。

Select DT.dataId, DT.dataelement, T1.reqid
From Table1 T1
Inner join DataTable DT
On T1.dataelementValues like '%' + DT.dataelement + '%' 

我现在无法对此进行测试,但应该提供您需要的行集,因为like运算符会导致一个T1行与相应的DT行匹配三次。