65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 SQL Server 2005 中的 XML 数据类型在 SQL 参数中传递数组

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.64/5 (10投票s)

2007年10月12日

3分钟阅读

viewsIcon

135848

downloadIcon

558

在 SQL Server 2005 中使用 XML 数据类型,我们可以将值数组从应用程序服务器传递到数据库。

引言

在 T-SQL 中,将值数组作为 SQL 参数传递一直很麻烦。在 SQL Server 2005 中,XML 数据类型可以帮助模拟数组。

背景

T-SQL 没有数组的概念;它只有简单类型(例如,INTEGERVARCHAR)。Web 或应用程序服务器的一个典型场景是使用多个参数调用存储过程。例如,您可能进行信息处理,并确定应该使用给定状态标记客户 ID 数组。实现该场景的直观方法是将客户 ID 列表传递给存储过程

private void PushStatus(int[] customerIDs, CustomerStatus status)
{
    CallSproc(customerIDs, status);
}

不幸的是,您将无法编写接受 INTEGER 数组作为输入参数的存储过程。实现该场景的一种可能方法是多次调用存储过程,每个 ID 调用一次

private void PushStatus(int[] customerIDs, CustomerStatus status)
{
    foreach(int id in customerIDs)
    {
        CallSproc(id, status);
    }
}

这是一种流行的方法,但它的可扩展性不好。如果您要传递的 ID 数组很大(例如,超过 10 个元素),则存储过程调用的延迟将开始降低整体操作的性能。为了使性能保持可接受,我们需要在一个调用中将整个数组传递到数据库服务器,或者至少比数组大小少得多地进行调用。在 SQL Server 2005 之前,一种流行的解决方案是将数组连接成一个字符串,并将该字符串传递给存储过程。该解决方案存在几个问题

  • 在 T-SQL 中拆分字符串是可能的,但这是一个繁琐且缓慢的过程。这是因为 T-SQL 不是一种优化用于操作字符串的语言。
  • 与所有序列化过程一样,您必须选择一个分隔符(例如管道),并禁止从输入中使用或转义此字符。 这在两端都引入了复杂性。
  • 输入是一个字符串(varchar 或 text),因此,从语义上讲,这种技术对于阅读存储过程的人来说是令人困惑的。

使用 XML

SQL Server 2005 的一个重要亮点是引入了 XML 数据类型。 XML 非常适合传输各种结构信息。 使用 XML,我们可以实现上一节中的场景。 我们只需将数组(例如 {42, 73, 2007})转换为 XML 文档

<list>
    <item>42</item>
    <item>73</item>
    <item>2007</item>
</list>

这种方法有很多优点

  • 使用 T-SQL 的 x-query 功能,可以很容易地从 T-SQL 中的 XML 文档中提取信息。
  • 序列化过程中存在特殊字符(例如 <>),但 XML 的转义机制是众所周知的,并且由 T-SQL 处理。
  • 存储过程的语义更加清晰,因为 XML 始终表示信息包。

Using the Code

本文中提出的迷你库由 C# 中的一个静态辅助类和一个 T-SQL 函数组成。 静态类有一个方法

public static SqlXml GetXml(IEnumerable list)
{
    //We don't use 'using' or dispose or close the stream, 

    //since it leaves in the return variable

    MemoryStream stream = new MemoryStream();

    using (XmlWriter writer = XmlWriter.Create(stream))
    {
        writer.WriteStartElement("list");

        foreach (object obj in list)
        {
            writer.WriteElementString("item", obj.ToString());
        }

        writer.WriteEndElement();
        stream.Position = 0;

        return new SqlXml(stream);
    }
}

它接受对象列表(任何类型的对象;它仅依赖于 ToString 实现)并返回一个 XML 变量,该变量已准备好提供给 SqlParameter。 在 SQL Server 上,该函数是一个内联表函数

CREATE FUNCTION [lm].[SplitList]
(
    @list AS XML
)
RETURNS TABLE
AS
RETURN
(
    SELECT tempTable.item.value('.', 'VARCHAR(MAX)') AS Item
    FROM @list.nodes('list/item') tempTable(item)
);

它接受一个 XML 参数并返回一个包含一列的表,其中每一行都是 XML 节点的内容。

结论

本文中显示的技术展示了将 XML 作为 SQL Server 2005 中的一等公民的另一个有趣的好处。将对象数组传递给存储过程可以提高批处理操作的性能。这可以提高应用程序的性能和可伸缩性。

© . All rights reserved.