2009-10-16 16 views
6

'daki özniteliklerini nasıl döndürebilirim Bir tabloda XML sütununda bir dizi öznitelikle birden çok öğe içeren bir pivot gerçekleştirmem gerekiyor. Her elemandaki özellikler her zaman aynıdır, ancak elemanların sayısı değişecektir. (Kullanıcı adı, ad, soyadı ve Newfield Bu örnekte) bunlara karşılık gelen fieldValue gibi niteliklerini Bir XML sütununun T-SQL

FormEntryId |    FormXML         | DateCreated 
==================================================================================== 
1   |<Root>             | 10/15/2009 
      | <Form>             | 
      | <FormData FieldName="Username" FieldValue="stevem" /> | 
      | <FormData FieldName="FirstName" FieldValue="Steve" /> | 
      | <FormData FieldName="LastName" FieldValue="Mesa" /> | 
      | </Form>             | 
      |</Root>             | 
      |               | 
------------------------------------------------------------------------------------ 
2   |<Root>             | 10/16/2009 
      | <Form>             | 
      | <FormData FieldName="Username" FieldValue="bobs" /> | 
      | <FormData FieldName="FirstName" FieldValue="Bob" /> | 
      | <FormData FieldName="LastName" FieldValue="Suggs" /> | 
      | <FormData FieldName="NewField" FieldValue="test" /> | 
      | </Form>             | 
      |</Root>             | 

ben her farklı AlanAdı için ayarlanmış bir sonuçla kadar rüzgar öznitelik değerleri lazım ... bana bir örnek vereyim değer. Ben statik sütunları

SELECT 
    FormEntryId, 
    FormXML.value('/Root[1]/Form[1]/FormData[@FieldName="Username"][1]/@FieldValue','varchar(max)') AS Username, 
    FormXML.value('/Root[1]/Form[1]/FormData[@FieldName="FirstName"][1]/@FieldValue','varchar(max)') AS FirstName, 
    FormXML.value('/Root[1]/Form[1]/FormData[@FieldName="LastName"][1]/@FieldValue','varchar(max)') AS LastName, 
    FormXML.value('/Root[1]/Form[1]/FormData[@FieldName="NewField"][1]/@FieldValue','varchar(max)') AS NewField, 
    DateCreated 
FROM FormEntry 

ile bunu yapmanın bir yolunu ettik

FormEntryId | Username | FirstName | LastName | NewField | DateCreated 
====================================================================== 
1   | stevem | Steve  | Mesa  | NULL  | 10/15/2009 
---------------------------------------------------------------------- 
2   | bobs  | Bob  | Suggs | test  | 10/16/2009 

Ancak bir yöntem olup olmadığını görmek istiyorum: Örneğin sonuçları Ben gibi görünecektir yukarıda verdi sütunların, "FieldName" özellik değerlerinin farklı kümelerine dayalı olarak dinamik olmasını sağlayın.

+0

+1. –

cevap

4

this dynamic pivot ve daha yakın zamanda this one'a bir göz atın - temel olarak sorgunuzu dinamik olarak oluşturmak için bu tekniği SELECT DISTINCT FieldName kullanabilmeniz gerekir.

DECLARE @template AS varchar(MAX) 
SET @template = 'SELECT 
    FormEntryId 
    ,{@col_list} 
    ,DateCreated 
FROM FormEntry' 

DECLARE @col_template AS varchar(MAX) 
SET @col_template = 'FormXML.value(''/Root[1]/Form[1]/FormData[@FieldName="{FieldName}"][1]/@FieldValue'',''varchar(max)'') AS {FieldName}' 

DECLARE @col_list AS varchar(MAX) 

;WITH FieldNames AS (
    SELECT DISTINCT FieldName 
    FROM FormEntry 
    CROSS APPLY (
     SELECT X.FieldName.value('@FieldName', 'varchar(255)') 
     FROM FormXML.nodes('/Root[1]/Form[1]/FormData') AS X(FieldName) 
    ) AS Y (FieldName) 
) 
SELECT @col_list = COALESCE(@col_list + ',', '') + REPLACE(@col_template, '{FieldName}', FieldName) 
FROM FieldNames 

DECLARE @sql AS varchar(MAX) 
SET @sql = REPLACE(@template, '{@col_list}', @col_list) 

EXEC (@sql) 
+0

Vay, bu çok etkileyici! Bunu örnek verilerim için işe aldım, ama Steve'in belirttiği gibi üzerinde çalışmam gereken bir dizi enjeksiyon atağı önleme ve düşüncenin olduğunu hayal ediyorum. Yardımın için teşekkürler! –

+0

Evet, SQL için AS QUOTENAME ({FieldName}) kullanabilirsiniz, ancak XQuery bölümünden çıkış yapmaya nereden başlayacağımı bilmiyorum: @FieldName = "{FieldName}". –

1

Dinamik Pivot değilmi:

İşte sorun için tam bir cevap (sütunlar görünmelidir sipariş bilerek belirgin niteliklerinden listesini oluştururken bir sütun sırası zayıflık var olduğuna dikkat edin) t iyi bir sebepten dolayı dile yerleşti. Sonuç yapısının bilinmesinden önce olası sütun adlarını içeren tablonun tamamını taramak gerekli olacaktır. Sonuç olarak, dinamik pivot ifadesinin tablo yapısı çalışma zamanından önce bilinmeyecekti. Bu, dilin ayrıştırılması ve yorumlanması ile ilgili birçok sorun yaratır.

Dinamik pivotu kendi başınıza uygulamaya karar verirseniz, SQL enjeksiyon fırsatlarına dikkat edin. Sonuçta sütun adları olarak kullanmayı planladığınız değerlere QUOTENAME veya eşdeğerini uyguladığınızdan emin olun. Kaynağınızda, sütun adlarına dönüşecek ayrı değerlerin sayısı, sonuç kümesinin izin verilen sütun sayısını aşarsa, hangi sonucu istediğinizi düşünün. Oldukça güzel kod oluşturma için

İlgili konular