2012-03-08 6 views
10

Ho questo xml:SQL Server: OPENXML rispetto a SELECT..FROM quando si ha a che fare con XML?

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

Task:

voglio elencare il a,b,c.

approccio 1:

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

approccio 2:

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

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

entrambi mi danno:

enter image description here

q Domanda:

che è il modo preferito?

È stato rilevato qualche vantaggi di quest'ultima contro l'ex (o viceversa)?

+1

Io personalmente preferisco l'approccio # 1 - è sa molto più intuitivo da me, e non richiede i passaggi aggiuntivi di 'sp_xml_preparedocument' ecc - semplicemente più facile da usare –

+2

@marc_s e insieme a quella ... significa # 1 può essere utilizzato in Vista e così via. –

risposta

9

Un semplice test dimostra che l'approccio 1 richiede meno tempo rispetto approccio 2. Non vorrei trarre conclusioni sul fatto che sia sempre il caso. Può dipendere da come è strutturato il tuo XML e da come devi interrogare l'XML.

stored procedure per test su:

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 

prova:

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 

approccio Risultato 1:

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

approccio Risultato 2:

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

(testato su SQL Server 2005.)

+0

Come può essere necessario meno tempo se @PraVn risponde al contrario? –

+0

@RoyiNamir - il costo della query non è lo stesso del tempo di esecuzione e quando si tratta di query XML non è necessario considerare il costo delle query. –

+0

(solo per un'idea) - come risolverebbe questo?http://stackoverflow.com/questions/10818115/cell-to-cell-comparison-in-sql-server (non preoccuparti di rispondere, rispondi in parole ...) grazie per il tuo tempo. –

2

preferisco # 2. provare il piano di esecuzione e vedere che il primo approch costa 97% in cui la cond una costa solo 3%

enter image description here

+1

grazie per lo sforzo: p.s. 3% relativo al lotto. qual è il lotto? dove sono gli altri 97%? –

+2

A mio parere, le stime dei costi di query non sono attendibili quando si tratta di utilizzare il tipo di dati XML. –

+1

@RoyiNamir mi sono imbattuto tboth le query in un unico lotto. 97% per il primo e 3% per il secondo – 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