TVF
TVF 过程或 TVF
外部数据源(与只访问本地数据)?
CLR TVF 或 CLR 过程
(只访问本地数据)T-SQL TVF 或过程
需要副作用?
过程
过程或 TVF
固定的结果架构?
过程或 TVF
过程
多个结果集?
过程
过程或 TVF
流化结果的能力?
CLR TVF
T-SQL TVF
对于本节的大部分内容,通过 SqlPipe 发送结果是与过程紧密相关的。即使在 CLR 触发器主体中 SqlPipe 是可用的并且返回结果是可能的,也很不提倡这种做法,因为使用在目标对象中定义的触发器发出数据处理语言 (DML) 或数据定义语言 (DDL) 语句可能会导致意外的结果。
将标量分解为行
经常需要在应用程序中传送多值参数。例如,在定单处理系统中,可能需要编写存储过程来将定单插入到 Orders 表中。存储过程中的参数之一可能是定单中的行项目。在这种情况下,您会遇到 T-SQL 限制,它不支持表值参数或缺乏集合数据类型(如数组)。解决这个问题的一种方法是,将集合编码为一个标量值(如 nvarchar 或 xml),然后将其作为参数传递给存储过程。在存储过程内,可以使用表值函数来接受标量输入,并将其转换成一组行,然后将这些行插入到 LineItems 表中。
虽然可以用 T-SQL 编写表值函数,但是用 CLR 实现它有两个好处:
•
System.Text 命名空间中的字符串处理函数使得编写表值函数更加容易。
•
CLR TVF 提供了更有效的流实现,这避免了将结果加载到工作表中。
下面的代码片段显示了如何实现一个表值函数,它接受以‘;’分隔的一组值作为输入字符串,并且以一组行(字符串中的每个值一行)的形式返回该字符串。请注意,MySqlReader 类的构造函数实现了大部分工作,它使用 System.String.Split 方法将输入字符串分解为数组。
// TVF that cracks a ';' separated list of strings into a result // set of 1 nvarchar(60)column called Value public static ISqlReader GetStrings(SqlString str) { return (ISqlReader)new MySqlReader(str); } public class MySqlReader : ISqlReader { private string[] m_strlist; private int m_iRow = -1; // # rows read //The core methods //Initialize list public MySqlReader(SqlString str) { //Split input string if not database NULL; //else m_strlist remains NULL if (!str.IsNull) { m_strlist = str.Value.Split(';'); } } // SECTION: Metadata related: Provide #, names, types of // result columns public int FieldCount { get { return 1; } } public SqlMetaData GetSqlMetaData(int FieldNo) { if (FieldNo==0) return new SqlMetaData("Value", SqlDbType.NVarChar, 60); else throw new NotImplementedException(); } // SECTION: Row navigation. Read is called until it returns // false. After each Read call, Get<TypeName> for each // column is called. public bool Read() { //Return empty result set if input is DB NULL //and hence m_strlist is uninitialized if (m_strlist==null) return false; m_iRow++; if (m






