// 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_iRow == m_strlist.Length) return false; return true; }
//Column getters //Implement Get<SqlTypeName> for each column produced by //the TVF; in this case just one. public SqlChars GetSqlChars(int i) { if (i == 0) return new SqlChars(m_strlist[m_iRow]); else throw new NotImplementedException(); }
//Methods not used by SqlServer omitted; //Actual implementation should provide an empty //implementation. ...
} // public class MySqlReader } // class StringFunctions;
[SqlProcedure] public static void Product(out SqlInt32 value) { SqlCommand cmd = SqlContext.GetCommand(); cmd.CommandText = "select intcolumn from tbl"; SqlDataReader r = cmd.ExecuteReader(); bool first = true; using (r) { while (r.Read()) //skip to the next row { if (first) { value = r.GetSqlInt32(0); first = false; } else { value *= r.GetSqlInt32(0); } } } }
可以使用 EXEC 语句来调用这一过程
EXEC Product @p OUTPUT
作为使用光标的 T-SQL 存储过程实现的 PRODUCT
可以创建 T-SQL 存储过程来执行查询和通过使用 T-SQL 光标循环访问结果,以执行计算。
create procedure TSQL_ProductProc (@product int output) as begin declare @sales int declare c insensitive cursor for select intcolumn from tbl open c fetch next from c into @sales
if @@FETCH_STATUS = 0 set @product = @sales
while @@FETCH_STATUS = 0 begin fetch next from c into @sales set @product = @product * @sales end
聚合算法细节。在 Order By 子句(如果查询中有)之前可能对 UDA 进行求值,因此不能保证传递给聚合函数的值的顺序。如果聚合算法需要按照特定的顺序使用值,则不能使用 UDA。同样地,UDA 从整组中使用值并且返回单一值。如果需要必须为组中的每个值返回值的聚合函数,则应该考虑使用存储过程或流表值函数来编写您的函数。详细信息请参见本文中的“产生结果”一节。