我有两个表,我需要比较数据并更新/插入一个表记录。我想要做的是我需要从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
答案 0 :(得分:1)
您可以尝试使用带有其他一些技巧的MERGE语句。
-- 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);
答案 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行匹配三次。