2011-11-29 75 views
0

我正在寫一個存儲過程來處理由用戶上傳的XML數據:驗證各個XML元素2008R2

<People> 
    <Person Id="1" FirstName="..." LastName="..." /> 
    <Person Id="2" FirstName="..." LastName="..." /> 
    <Person Id="3" FirstName="..." LastName="..." /> 
    <Person Id="4" FirstName="..." LastName="..." /> 
    <Person Id="5" FirstName="..." LastName="..." /> 
</People> 

我想用一個模式來確保實體是有效的,但我不希望整個過程因爲一個無效的實體而失敗。相反,我想將所有無效實體記錄到一個表中,並按正常方式處理有效實體。

有沒有推薦的方法來做到這一點?

回答

1

純SQL的方法是:

  1. 創建一個架構集合定義<Person>

    CREATE XML SCHEMA COLLECTION [dbo].[testtest] AS 
    N'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
        <xs:element name="Person"> 
         <xs:complexType> 
         <xs:attribute name="Id" type="xs:int" use="required"/> 
         <xs:attribute name="FirstName" type="xs:string" use="required"/> 
         <xs:attribute name="LastName" type="xs:string" use="required"/> 
         </xs:complexType> 
        </xs:element> 
        </xs:schema> 
    ' 
    

    (一次性操作)

  2. 有一個XML查詢選擇作爲單獨的行,來自<People>的每個<Person>節點。

  3. 在該查詢上聲明一個遊標,並將每行都選擇到一個無類型的xml變量中。選擇之後,嘗試從try-catch塊內分配一個類型化的xml變量。

生成的代碼看起來像:

declare @source xml = N' 
    <People> 
     <Person Id="1" FirstName="..." LastName="..." /> 
     <Person Id="2" FirstName="..." LastName="..." /> 
     <Person Id="f" FirstName="..." LastName="..." /> 
     <Person Id="4" FirstName="..." LastName="..." /> 
     <Person Id="5" FirstName="..." LastName="..." /> 
    </People>'; 

declare foo cursor 
local 
forward_only 
read_only 
for 
    select t.p.query('.') 
    from @source.nodes('People/Person') as t(p) 
; 

declare @x xml (dbo.testtest); 
declare @x_raw xml; 

open foo; 

fetch next from foo into @x_raw; 

while @@fetch_status = 0 
begin 
    begin try 
    set @x = @x_raw; 
    print cast(@x_raw as nvarchar(max)) + ': OK'; 
    end try 
    begin catch 
    print cast(@x_raw as nvarchar(max)) + ': FAILED'; 
    end catch; 

    fetch next from foo into @x_raw; 
end; 

close foo; 
deallocate foo; 

結果:

<Person Id="1" FirstName="..." LastName="..."/>:OK
<Person Id="2" FirstName="..." LastName="..."/>:OK
<Person Id="f" FirstName="..." LastName="..."/>:失敗
<Person Id="4" FirstName="..." LastName="..."/>:OK
<Person Id="5" FirstName="..." LastName="..."/>:OK


一個更簡單的方法是創建一個CLR存儲過程將在.NET語言解析XML。

+0

你能給我一個XML查詢的例子來選擇每個元素作爲一個單獨的行嗎?另外,如果我使用CLR存儲過程,會不會影響存儲過程的性能? –

+0

@JustinRusbatch查看修改。至於性能,我認爲CLR實際上會更快,但試試看。 – GSerg