2012-03-08 41 views
10

tengo unas pocas cosas xml:SQL Server: OPENXML vs SELECT..FROM cuando se trata de XML?

DECLARE @x XML 
SET @x = 
    '<data> 
     <add>a</add> 
     <add>b</add> 
     <add>c</add> 
    </data>'; 

Tarea:

Quiero que la a,b,c.

enfoque 1:

SELECT s.value('.', 'VARCHAR(8000)') AS [ADD] 
FROM @x.nodes('/data/add') AS t(s) 

enfoque 2:

DECLARE @idoc INT 
EXEC sp_xml_preparedocument @idoc OUTPUT, @x 

SELECT * 
FROM OPENXML(@idoc, '/data/add', 2) 
     WITH ([add] NVARCHAR(MAX) '.') 

ambos me dan:

enter image description here

q Pregunta:

¿cuál es la forma preferida?

¿Hay alguna ventaja de esta última frente a la anterior (o viceversa)?

+1

yo personalmente prefiero el enfoque # 1 - es mucho más intuitivo sa para mí, y que no requiere los pasos adicionales de 'sp_xml_preparedocument' etc - simplemente más fácil de usar –

+2

@marc_s Y junto con eso ... significa # 1 se puede utilizar en Vistas y tal. –

Respuesta

9

Una prueba simple muestra que el enfoque lleva menos tiempo que enfoque 2. No sacaría ninguna conclusión acerca de que siempre sea el caso. Puede depender de cómo está estructurado su XML y cómo necesita consultar el XML.

Los procedimientos almacenados para probar en:

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 

prueba:

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 

enfoque Resultado 1:

SQL Server Execution Times: 
    CPU time = 63 ms, elapsed time = 70 ms. 

enfoque Resultado 2:

SQL Server Execution Times: 
    CPU time = 156 ms, elapsed time = 159 ms. 

(probado en SQL Server 2005.)

+0

¿Cómo puede llevar menos tiempo si @PraVn responde que los zapatos son opuestos? –

+0

@RoyiNamir: el costo de la consulta no es el mismo que el tiempo de ejecución y cuando se trata de consultas XML, no se debe confiar en el costo de la consulta. –

+0

(solo por una idea) - ¿Cómo resolverías esto?http://stackoverflow.com/questions/10818115/cell-to-cell-comparison-in-sql-server (no se moleste en responder, solo responda con palabras ...) gracias por su tiempo. –

2

Prefiero # 2. tratar el plan de ejecución y ver que el primer approch cuesta 97% en tanto que la cond uno cuesta sólo el 3%

enter image description here

+1

gracias por el esfuerzo: p.s. 3% relativo al lote. ¿Cuál es el lote? donde estan el otro 97%? –

+2

En mi opinión, no se debe confiar en las estimaciones de costos de consulta cuando se trata de usar el tipo de datos XML. –

+1

@RoyiNamir Ejecuté ambas consultas en un solo lote. 97% para la primera y 3% para la segunda – PraveenVenu

0
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 
Cuestiones relacionadas