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

How to insert fields extracted from XML in one table into another table?

我有一个 table(比如 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)

现在,我想构建另一个 table(比如 heads),具有相同的 primary_key 和列 dl_identifiercreated_on,并且 shipping_date 填充了从 messages.xml_data 中提取的信息。它应该只处理新的 messages.xml_data(尚未完成提取)。

到目前为止,我正在考虑左外连接 tables 来检测丢失的 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 中?

提供 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');

--该语句将从"messages"中的XML中读取值, --但会忽略那些 ID 存在于另一个 table 中的 -- 你可以用 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;