解析/处理XML并插入SQL表
后续行动来自: 我已经有了一些SQL代码,可以循环遍历QABLOCKs并打印它们。打印将在生产中更改为插入解析/处理XML并插入SQL表,sql,xml,sql-server-2005,xquery,Sql,Xml,Sql Server 2005,Xquery,后续行动来自: 我已经有了一些SQL代码,可以循环遍历QABLOCKs并打印它们。打印将在生产中更改为插入 -- XML instance DECLARE @x1 XML SELECT @x1 = ' <tests> <test id="1"> <qablock number="1"> <question>What is 1 + 1?</question>
-- XML instance
DECLARE @x1 XML
SELECT @x1 =
'
<tests>
<test id="1">
<qablock number="1">
<question>What is 1 + 1?</question>
<explanation>It"s 2.</explanation>
<options>
<option number="1" value="1" correct="0" />
<option number="2" value="2" correct="1" />
<option number="3" value="3" correct="0" />
<option number="4" value="4" correct="0" />
<option number="5" value="5" correct="0" />
</options>
</qablock>
<qablock number="2">
<question>What is 2 + 2?</question>
<explanation>It"s 4.</explanation>
<options>
<option number="1" value="1" correct="0" />
<option number="2" value="2" correct="0" />
<option number="3" value="3" correct="0" />
<option number="4" value="4" correct="1" />
<option number="5" value="5" correct="0" />
</options>
</qablock>
</test>
</tests>
'
DECLARE
@cnt INT,
@totCnt INT,
@child XML
-- counter variables
SELECT
@cnt = 1,
@totCnt = @x1.value('count(/tests/test/qablock)','INT')
-- loop
WHILE @cnt <= @totCnt BEGIN
SELECT
1 AS tests_id, --this is hard-coded
@cnt AS qablock_number,
@x1.value('(/tests/test/qablock[position()=sql:variable("@cnt")]/question/text())[1]','varchar(500)') AS question,
@x1.value('(/tests/test/qablock[position()=sql:variable("@cnt")]/explanation/text())[1]','varchar(1000)') AS explanation
PRINT 'Processing Child Element: ' + CAST(@cnt AS VARCHAR)
PRINT 'Child element: ' + CAST(@child AS VARCHAR(max))
PRINT ''
-- increment the counter variable
SELECT @cnt = @cnt + 1
END
我不知道这是否是正确的程序,但至少它似乎是有效的。接下来我要做的是运行另一个类似的脚本,它循环遍历所有选项并打印它们。对于每个选项,我需要打印:QABLOCK编号、选项编号、选项值和选项是否正确。我甚至不能靠近以下是到目前为止我得到的信息:
-- XML instance
DECLARE @x1 XML
SELECT @x1 =
'
<tests>
<test id="1">
<qablock number="1">
<question>What is 1 + 1?</question>
<explanation>It"s 2.</explanation>
<options>
<option number="1" value="1" correct="0" />
<option number="2" value="2" correct="1" />
<option number="3" value="3" correct="0" />
<option number="4" value="4" correct="0" />
<option number="5" value="5" correct="0" />
</options>
</qablock>
<qablock number="2">
<question>What is 2 + 2?</question>
<explanation>It"s 4.</explanation>
<options>
<option number="1" value="1" correct="0" />
<option number="2" value="2" correct="0" />
<option number="3" value="3" correct="0" />
<option number="4" value="4" correct="1" />
<option number="5" value="5" correct="0" />
</options>
</qablock>
</test>
</tests>
'
DECLARE
@cnt INT,
@totCnt INT,
@child XML
-- counter variables
SELECT
@cnt = 1,
@totCnt = @x1.value('count(/tests/test/qablock/options/option)','INT')
-- loop
WHILE @cnt <= @totCnt BEGIN
SELECT
1 AS tests_id, --hard-coded value
@x1.value('(/tests/test/qablock/@number)[1]','varchar(500)') AS qablock_number,
@x1.value('(/tests/test/qablock/options/option[position()=sql:variable("@cnt")]/@number)[1]','varchar(500)') AS option_number
PRINT 'Processing Child Element: ' + CAST(@cnt AS VARCHAR)
PRINT 'Child element: ' + CAST(@child AS VARCHAR(max))
PRINT ''
-- increment the counter variable
SELECT @cnt = @cnt + 1
END
所以,很明显这是一团糟,但我似乎不知道该改变什么
首先,我不知道如何获取当前选项的父块编号
第二,只有我的前5个选项编号正确显示其编号,第二个5个选项编号显示为空
另外,部分代码来自:
这应该可以做到:
-- XML instance
DECLARE @x1 XML
SELECT @x1 =
'
<tests>
<test id="1">
<qablock number="1">
<question>What is 1 + 1?</question>
<explanation>It"s 2.</explanation>
<options>
<option number="1" value="1" correct="0" />
<option number="2" value="2" correct="1" />
<option number="3" value="3" correct="0" />
<option number="4" value="4" correct="0" />
<option number="5" value="5" correct="0" />
</options>
</qablock>
<qablock number="2">
<question>What is 2 + 2?</question>
<explanation>It"s 4.</explanation>
<options>
<option number="1" value="1" correct="0" />
<option number="2" value="2" correct="0" />
<option number="3" value="3" correct="0" />
<option number="4" value="4" correct="1" />
<option number="5" value="5" correct="0" />
</options>
</qablock>
</test>
</tests>
'
declare @testCount int
, @testIndex int
, @qaCount int
, @qaIndex int
, @optCount int
, @optIndex int
, @testId int
, @qaNo int
, @question nvarchar(500)
, @explanation nvarchar(500)
, @optNo int
, @optVal int
, @optCorrect bit
--for each test
set @testCount = @x1.value('count(/tests/test)','int')
set @testIndex = 1
while @testIndex <= @testCount
begin
--insert a record for this test
set @testId = @x1.value('(/tests/test[sql:variable(''@testIndex'')]/@id)[1]','int')
print 'insert into tests (id, ...) values (' + + cast(@testId as nvarchar(9)) + ')'
print 'set @testIdDB = scope_identity()' --if we're using db generated ids rather than relying on the ids in the imported xml
--for each qablock
set @qaCount = @x1.value('count(/tests/test[sql:variable(''@testIndex'')]/qablock)','int')
set @qaIndex = 1
while @qaIndex <= @qaCount
begin
--insert a qa record
select @qaNo = @x1.value('(/tests/test[sql:variable(''@testIndex'')]/qablock[sql:variable(''@qaIndex'')]/@number)[1]','int')
, @question = @x1.value('(/tests/test[sql:variable(''@testIndex'')]/qablock[sql:variable(''@qaIndex'')]/question/text())[1]','nvarchar(500)')
, @explanation = @x1.value('(/tests/test[sql:variable(''@testIndex'')]/qablock[sql:variable(''@qaIndex'')]/explanation/text())[1]','nvarchar(500)')
print 'insert into qa (testId, qaNo, Question, Explanation) values (@testIdDB, ' + cast(@qaNo as nvarchar(9)) + ', ' + quotename(@question,'''') + ', ' + quotename(@explanation,'''') + ')'
print 'set @qaIdDB = scope_identity()'
--for each option
set @optCount = @x1.value('count(/tests/test[sql:variable(''@testIndex'')]/qablock[sql:variable(''@qaIndex'')]/options/option)','int')
set @optIndex = 1
while @optIndex <= @optCount
begin
--insert an option record
select @optNo = @x1.value('(/tests/test[sql:variable(''@testIndex'')]/qablock[sql:variable(''@qaIndex'')]/options/option[sql:variable(''@optIndex'')]/@number)[1]','int')
, @optVal = @x1.value('(/tests/test[sql:variable(''@testIndex'')]/qablock[sql:variable(''@qaIndex'')]/options/option[sql:variable(''@optIndex'')]/@value)[1]','int')
, @optCorrect = @x1.value('(/tests/test[sql:variable(''@testIndex'')]/qablock[sql:variable(''@qaIndex'')]/options/option[sql:variable(''@optIndex'')]/@correct)[1]','bit')
print 'insert into tests (qaId, number, value, isCorrect) values (@qaIdDB, ' + cast(@optNo as nvarchar(9)) + ', ' + cast(@optVal as nvarchar(9)) + ', ' + cast(@optCorrect as nchar(1)) + ')'
set @optIndex = @optIndex + 1
end
set @qaIndex = @qaIndex + 1
end
set @testIndex = @testIndex + 1
end
Heya mate-现在写一个完整的答案,但是空值是因为您的计数从1到10,而选项在1-5的两个块中,即位置在第6个选项元素上重置为1。快速修复方法是:/tests/test/qablock/options/option/@number[sql:variable@cnt]非常感谢您即将回复。上面的快速修复代码在SSMS中生成错误:XQuery[value]:“value”需要单例或空序列,但找到的操作数类型为“xdt:untypedAtomic*”,因此将等待您的完整答复:我甚至不知道做一个WHILE循环是否是正确的方法。似乎这个网站从未使用过它们:天哪,谢谢你的工作!我将仔细研究这个问题,并试图根据您的示例找出所有问题。再次感谢您的回复!关于编辑,是的,现在这更是我所期待的!我们将仔细研究它,并希望从中学到很多东西!无需担心-感谢您的积极反馈:。任何问题都可以让我大喊一声。我怎么能在外面和你联系呢?你的博客没有联系方式。当然,但如果它与问题有关,我建议使用stack overflow,因为这样,当我忙的时候,其他人可以弥补我的不足,当我给出不好的建议时,他们也可以指出。你可以用我的SO用户名和gmail联系,这样可以避免垃圾邮件。
select x.value('@id','int') testId
FROM @x1.nodes('/tests/test') d(x)
select x.value('../@id','int') parentTestId
, x.value('@number','int') qaNumber
, x.value('(question/text())[1]','nvarchar(500)') question
, x.value('(explanation/text())[1]','nvarchar(500)') explanation
FROM @x1.nodes('/tests/test/qablock') d(x)
select x.value('../../@number','int') parentQaNumber
, x.value('@number','int') number
, x.value('@value','int') value
, x.value('@correct','bit') correct
FROM @x1.nodes('/tests/test/qablock/options/option') d(x)