2010-09-09 57 views
2

試圖瞭解爲什麼你不能使用SQL Server中的XML節點的功能時,該值類型使用SQL_VARIANT?我有一個場景,我將動態解析一些XML輸入,並能夠使用sql_variant將是一個很好的替代方案,以分配數據類型變量或在sys.columns上執行查找。的SQL Server 2008 - SQL_VARIANT在XML nodes.value

例子:

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[XmlSourceTable]') AND type in (N'U')) 
DROP TABLE [dbo].[XmlSourceTable] 
GO 
CREATE TABLE [dbo].[XmlSourceTable](
    [RecordId] [int] IDENTITY(1,1) NOT NULL, 
    [XmlData] [xml] NOT NULL, 
PRIMARY KEY CLUSTERED 
(
    [RecordId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 

DECLARE @XML XML ='<?xml version="1.0" ?> 
<Root> 
     <Person> 
      <Name>Simon</Name> 
      <Age>20</Age> 
      <Skills> 
        <Skill>Cooking</Skill> 
        <Skill>Cleaning</Skill> 
      </Skills> 
     </Person> 
     <Person> 
      <Name>Peter</Name> 
      <Age>21</Age> 
      <Skills> 
        <Skill>Ironing</Skill> 
      </Skills> 
     </Person> 
</Root>' 

INSERT INTO XmlSourceTable(XmlData) 
SELECT @XML 

GO 

SELECT * FROM XmlSourceTable 
GO 
SELECT 
     pref.value('(Name/text())[1]', 'varchar(50)') as PersonName, 
     pref.value('(Age/text())[1]', 'int') as PersonAge, 
     pref.query('Skills') as PersonSkills 
FROM 
     XmlSourceTable CROSS APPLY 
     XmlData.nodes('/Root/Person') AS People(pref) 

所以不是:

SELECT * FROM XmlSourceTable 
GO 
SELECT 
     pref.value('(Name/text())[1]', 'varchar(50)') as PersonName, 
     pref.value('(Age/text())[1]', 'int') as PersonAge, 
     pref.query('Skills') as PersonSkills 
FROM 
     XmlSourceTable CROSS APPLY 
     XmlData.nodes('/Root/Person') AS People(pref) 

這將是很好的使用方法:

SELECT * FROM XmlSourceTable 
GO 
SELECT 
     pref.value('(Name/text())[1]', 'sql_variant') as PersonName, 
     pref.value('(Age/text())[1]', 'sql_variantt') as PersonAge, 
     pref.query('Skills') as PersonSkills 
FROM 
     XmlSourceTable CROSS APPLY 
     XmlData.nodes('/Root/Person') AS People(pref) 

但我得到這個錯誤: 消息9500,級別16 ,狀態1,行1 VALUE方法中使用的數據類型'sql_variant')是無效的。

反正使用SQL_VARIANT中的節點功能?

謝謝,

小號

回答

3

sql_variant是一個元類型,在值存儲的實際類型的數據(INT,炭,浮動,日期等)的。問題是,XML表達做有型:是什麼樣的('Name/text())[1] XPath表達式結果的類型?我知道你可以爭辯說如果 XML有一個模式,可以推斷出與該節點/屬性/元素相關聯的xs模式類型,但我會說也許你可以推斷出該類型,而你仍然剩下的絕大多數方案較少的XML文檔的使用有...這就是爲什麼.value() XML方法需要一個類型,因此它可以強制在XML中發現到適當類型的文本。

值得注意的一件事是,大多數XML值可以提取爲VARCHAR,這將提供該元素/屬性的原始XML文本。然後,您可以將文本轉換爲適當的列。但我認爲做你做了什麼,現在(查找列類型,使用適當的類型動態生成的XPath /類型)是更好

+0

感謝萊姆斯....有道理。 – scarpacci 2010-09-09 17:43:34