如何将从XML提取的字段从一个表插入另一个表?

时间:2018-08-12 22:23:44

标签: xml tsql sql-server-2014

我有一个表(例如messages),其中有primary_keyxml_data。我知道如何从一个xml_data值中提取多个值,例如:

DECLARE @x XML = 'the XML value'

;WITH XMLNAMESPACES (
    'http://somenamespace/document' AS msg,
    'http://somenamespace/externalMessage' AS dat
)
SELECT c.value('(dat:delivery_list/dat:identifier)[1]', 'varchar(20)') AS dl_identifier,
       c.value('(dat:created_on)[1]', 'datetime2(0)') AS created_on,
       c.value('(dat:delivery_list/dat:shipping_date)[1]', 'datetime2(0)') AS shipping_date
FROM @x.nodes('/msg:data/msg:body/msg:request/msg:data/dat:operation/dat:data/dat:external_message') AS t(c)

现在,我要构建另一个表(例如heads),该表具有相同的primary_key和列dl_identifiercreated_onshipping_date填充了从messages.xml_data中提取的信息。它应该只处理新的messages.xml_data(尚未提取)。

到目前为止,我正在考虑将表的左侧连接起来以检测丢失的heads记录,如下所示:

SELECT m.primary_key,
       m.xml_data
  FROM messages AS m
       LEFT OUTER JOIN heads AS h
            ON h.primary_key = m.primary_key
               AND m.xml_data IS NOT NULL
 WHERE h.primary_key IS NULL

它选择所需的m.xml_data。是否可以在不使用光标的情况下将从m.xml_data(以及primary_key)中提取的值插入heads中?

1 个答案:

答案 0 :(得分:1)

提供MCVE最有帮助。看下面的例子:

--a mockup table to simulate your messages
DECLARE @tblMessages TABLE (ID INT IDENTITY PRIMARY KEY, xml_data XML);
--I insert 4 messages
INSERT INTO @tblMessages VALUES ('<root><test a="test 1.1" /><test a="test 1.2" /></root>')
                               ,('<root><test a="test 2.1" /><test a="test 2.2" /></root>')
                               ,('<root><test a="test 3.1" /></root>')
                               ,('<root><test a="test 4.1" /><test a="test 4.2" /><test a="test 4.3" /></root>');

--a mockup table to simulate your "heads" table
DECLARE @tblExtractedValues TABLE(ID INT IDENTITY PRIMARY KEY 
                                 ,message_ID INT NOT NULL /*always use names constaints and you might add FOREIGN KEY REFERENCES messages(primary_key)*/
                                 ,ExtractedValue_test VARCHAR(100));
--Let's simulate, that messages 1 and 3 are extracted already
INSERT INTO @tblExtractedValues VALUES(1,'test 1.1')
                                     ,(1,'test 1.2')
                                     ,(3,'test 3.1');

-此语句将从“消息”中的XML中读取值, -但将省略其他表中存在ID的那些 -您可以用INSERT注释掉该行,以查看SELECT的结果

INSERT INTO @tblExtractedValues(message_ID,ExtractedValue_test)                                  
SELECT m.ID
      ,t.value('@a','varchar(100)')
FROM @tblMessages m
CROSS APPLY m.xml_data.nodes('/root/test') A(t)
WHERE NOT EXISTS(SELECT 1 
                 FROM @tblExtractedValues ev
                 WHERE ev.message_ID=m.ID);

--Look at the order of insertion. 1 and 3 have lower IDs than 2 and 4
SELECT * FROM @tblExtractedValues;