SQL Server: OPENXML vs SELECT..FROM при работе с XML?
У меня есть этот xml:
DECLARE @x XML
SET @x =
'<data>
<add>a</add>
<add>b</add>
<add>c</add>
</data>';
Задача:
Я хочу перечислить a,b,c
.
подход 1:
SELECT s.value('.', 'VARCHAR(8000)') AS [ADD]
FROM @x.nodes('/data/add') AS t(s)
подход 2:
DECLARE @idoc INT
EXEC sp_xml_preparedocument @idoc OUTPUT, @x
SELECT *
FROM OPENXML(@idoc, '/data/add', 2)
WITH ([add] NVARCHAR(MAX) '.')
оба из них дают мне:
![enter image description here]()
вопрос:
который является предпочтительным способом?
Есть ли какие-либо преимущества последнего против прежнего (или наоборот)?
Ответы
Ответ 1
Простой тест показывает, что ваш подход 1 занимает меньше времени, чем подход 2. Я бы не делал никаких выводов о том, что это всегда так. Это может зависеть от того, как структурирован ваш XML и как вам нужно запрашивать XML.
Сохраненные процедуры для проверки:
create procedure TestXML
@X xml
as
set nocount on
select X.N.value('.', 'varchar(8000)')
from @X.nodes('/root/item') as X(N)
go
create procedure TestOpenXML
@X xml
as
set nocount on
declare @idoc int
exec sp_xml_preparedocument @idoc out, @X
select value
from openxml(@idoc, '/root/item',1)
with (value varchar(8000) '.')
exec sp_xml_removedocument @idoc
Тест:
declare @X xml
set @X =
(
select number as '*'
from master..spt_values
for xml path('item'), root('root'), type
)
set statistics time on
exec TestXML @X
exec TestOpenXML @X
Результат 1:
SQL Server Execution Times:
CPU time = 63 ms, elapsed time = 70 ms.
Результат 2:
SQL Server Execution Times:
CPU time = 156 ms, elapsed time = 159 ms.
(проверено на SQL Server 2005.)
Ответ 2
Я предпочитаю # 2. попробуйте выполнить план выполнения и убедитесь, что первый аспект составляет 97%, а в случае, если конв стоит всего 3%
![enter image description here]()
Ответ 3
SET NOCOUNT ON;
DECLARE @BankXml VARCHAR(MAX) = '<ROOT><ITEM BAF="HI" /></ROOT>'
DECLARE @ErrMsg VARCHAR(MAX) ='',@XmlId INT,@TranCount INT
CREATE TABLE #tmptbl(BAF VARCHAR(10))
IF (@BankXml IS NOT NULL)
BEGIN
EXEC SP_XML_PREPAREDOCUMENT @XmlId OUTPUT, @BankXml
INSERT INTO #tmptbl(BAF)
SELECT BAF
FROM OPENXML(@XmlId, 'ROOT/ITEM', 1) WITH
(
BAF VARCHAR(10)
)
END
BEGIN TRY
IF @@TRANCOUNT = 0
SET @TranCount = 1
IF @TranCount=1
BEGIN TRAN
IF 1=1
BEGIN
SELECT BAF FROM #tmptbl
END
IF @TranCount = 1
COMMIT TRAN
END TRY
BEGIN CATCH
IF @@TRANCOUNT = 1 AND @TranCount = 1
ROLLBACK TRAN
SET @ErrMsg = 'Error : ' + @ErrMsg + ' : ' + ERROR_MESSAGE()
RAISERROR(@ErrMsg,16,1)
END CATCH