我有一个表(例如messages
),其中有primary_key
和xml_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_identifier
,created_on
和shipping_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
中?
答案 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;