例如,下面的 C# 代码片段表示一个存储过程,它读取 XML 文档(来自 MSDN 的 Really Simple Syndication [RSS] 供给),使用 System.Xml 类进行解析,并且以相关的形式返回信息。请注意,这些代码应该创建为 EXTERNAL_ACCESS(或 UNSAFE)程序集,因为访问 Internet 所需的代码访问安全 (CAS) 权限只有在这些权限集中才是可用的。
// Retrieve the RSS feed XPathDocument doc = new XPathDocument("http://msdn.microsoft.com/sql/rss.xml"); XPathNavigator nav = doc.CreateNavigator(); XPathNodeIterator i = nav.Select("//item"); // create metadata for four columns // three of them are string types and one of the is a datetime SqlMetaData[] rss_results = new SqlMetaData[4]; rss_results[0] = new SqlMetaData("Title", SqlDbType.NVarChar, 250); rss_results[1] = new SqlMetaData("Publication Date", SqlDbType.DateTime); rss_results[2] = new SqlMetaData("Description", SqlDbType.NVarChar, 2000); rss_results[3] = new SqlMetaData("Link", SqlDbType.NVarChar, 1000); // construct the record which holds metadata and data buffers SqlDataRecord record = new SqlDataRecord(rss_results); // cache a SqlPipe instance to avoid repeated calls to SqlContext.GetPipe() SqlPipe sqlpipe = SqlContext.GetPipe(); // send the metadata, do not send the values in the data record sqlpipe.SendResultsStart(record, false); // for each xml node returned, extract four pieces // of information and send back each item as a row while (i.MoveNext()) { record.SetString(0, (string) i.Current.Evaluate("string(title[1]/text())")); record.SetDateTime(1, DateTime.Parse((string) i.Current.Evaluate("string(pubDate[1]/text())"))); record.SetString(2, (string) i.Current.Evaluate("string(description[1]/text())")); record.SetString(3, (string) i.Current.Evaluate("string(link[1]/text())")); sqlpipe.SendResultsRow(record); } // signal end of results sqlpipe.SendResultsEnd();
注 在 SendResultsStart 和 SendResultsEnd 调用之间,SqlPipe 被设置为繁忙状态,调用除 SendResultsRow 之外的任何 Send 方法都会导致错误发生。SqlPipe 处于繁忙状态中时,SendingResults 属性被设置为 TRUE。 表值函数 CLR 集成也启用了对用托管语言编写的表值函数 (TVF) 的支持。与 T-SQL 相似,TVF 主要用于返回表结果。最显著的不同在于,T-SQL 表值函数临时将结果存储在工作表中,而 CLR TVF 则能够对产生的结果数据进行流式处理。这意味着结果在从函数返回之前不需要物化。 注 T-SQL 还具有内联 TVF 的概念,即不临时存储结果。内联 TVF 在大部分语义上便于指定子查询(可能带有参数)。 托管 TVF 返回 ISqlReader 接口,这是由 SqlClient 和 SqlServer (in-proc) 托管提供程序中的 SqlDataReader 实现的一种只进光标抽象。查询处理器调用此接口上的 Read() 方法,以在每行返回 FALSE 之前获取它。 将上面的示例改为返回来自 RSS 供给的信息,返回结果的代码如下所示(不包括未实现的方法): [SqlFunction] public static ISqlReader tvf1() { return (ISqlReader)new RssReader(); } public class RssReader : ISqlReader { SqlMetaData[] rss_results = null; XPathDocument doc; XPathNavigator nav; XPathNodeIterator i; // Construct helper class, initializing metadata for the results // reading from the RSS feed, creating the iterator public RssReader() { rss_results = new SqlMetaData[4]; rss_results[0] = new SqlMetaData("Title", SqlDbType.NVarChar, 250); rss_results[1] = new SqlMetaData("Publication Date", SqlDbType.DateTime); rss_results[2] = new SqlMetaData("Description", SqlDbType.NVarChar, 2000); rss_results[3] = new SqlMetaData("Link", SqlDbType.NVarChar, 1000); // Retrieve the RSS feed doc = new XPathDocument("http://msdn.microsoft.com/sql/rss.xml"); nav = doc.CreateNavigator(); i = nav.Select("//item"); } // # of columns returned by the function public int FieldCount { get { return rss_results.Length; } } // metadata for each of the columns public SqlMetaData GetSqlMetaData(int FieldNo) { return rss_results[FieldNo]; } // Read method positions the navigator iterator on next element public bool Read() { return i.MoveNext(); } // methods to return each column public Object GetValue(int FieldNo) { switch (FieldNo) { case 0: return new SqlString((string) i.Current.Evaluate("string(title[1]/text())")); case 1: return new SqlDateTime(DateTime.Parse( (string)i.Current.Evaluate("string(pubDate[1]/text())"))); case 2: return new SqlString((string) i.Current.Evaluate("string(description[1]/text())")); case 3: return new SqlString((string) i.Current.Evaluate("string(link[1]/text())")); } return null; } public string GetString(int i) { return (string)GetValue(i); } public DateTime GetDateTime(int i) { return (DateTime)GetValue(i); } public SqlChars GetSqlCharsRef(int i) { return new SqlChars((SqlString)GetValue(i)); } public SqlChars GetSqlChars(int i) { return new SqlChars((SqlString)GetValue(i)); } public SqlDateTime GetSqlDateTime(int i) { return (SqlDateTime)GetValue(i); } ... } 使用来自此表值函数的结果的一种简单查询如下所示: select title, pubdate, description, link from dbo.GetRssFeed() 显然可以用此数据的 TVF 形式来表示更丰富的查询。假定函数 CanonicalURL() 会返回规范的 URL 版本。现在,可以使用规范的 URL 很容易地返回来自 RSS 供给的数据: sele






