SQL Server 2008 - XML 节点中的 sql_variant.value

标签 sql t-sql sql-server-2008

尝试了解为什么在 SQL Server 中使用 XML 节点函数时不能使用 sql_variant 作为值类型?我有一个场景,我将动态解析一些 XML 输入,并且能够使用 sql_variant 将是一个很好的替代方案,可以替代分配数据类型变量或在 sys.columns 上进行查找。

示例:

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?

谢谢

最佳答案

sql_variant 是一种元类型,它在值中存储数据的实际类型(int、char、float、date 等)。问题是 XML 表达式没有类型:像 ('Name/text())[1] 这样的 XPath 表达式结果的类型是什么?我理解您可能会说,如果 XML 有架构,就可以推断出与该节点/属性/元素关联的 xs 架构类型,但我想说也许您可以推断出类型,但仍然仍然使用着绝大多数无模式 XML 文档...这就是 .value() XML 方法的原因需要一个类型,因此它可以将 XML 中找到的文本强制转换为正确的类型。

值得注意的一件事是,大多数 XML 值都可以提取为 VARCHAR,这将给出该元素/属性的原始 XML 文本。然后您可以将文本转换为适当的列。但我认为现在做的事情(查找列类型,使用正确的类型动态构建 XPath/类型)更好

关于SQL Server 2008 - XML 节点中的 sql_variant.value,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3677980/

相关文章:

SQL Server 2008默认用户名

sql - 在 Entity Framework 中使用正则表达式进行搜索

sql - MySQL - 查找时间重叠

mysql - : HAVING c2. hacker_id <> c.hacker.id 这行的含义是什么?

sql-server - "Rows where Any 3 out of 7 fields aren' t 空白“条件的选项

sql - 如果数字为 0.00,如何显示文本值 'X'。 SQL Server、存储过程

sql - 从 SQL 分析时间相关的事件日志

sql - 使用 Access 的 VBA 追加查询

sql - Transact Sql LEFT 函数奇怪的输出

sql - 在 SQL Server 中查看与表