|
Программирование >> Программирование баз данных
using System; using System.Data; using System.Data.SqlClient; using System.Data.SqlTypes; using Microsoft.SqlServer.Server; [Serializable] [Microsoft.SqlServer.Server.SqlUserDefinedAggregate(Format.Native)] public struct ExampleAggregate public void InitO В этом месте должен находиться пользовательский код public void Accumulate(SqlString Value) В этом месте должен находиться пользовательский код public void Merge(ExampleAggregate Group) В этом месте должен находиться пользовательский код public SqlString Terminate() В этом месте должен находиться пользовательский код return new SqlString( ); Это - вспомогательная переменная private int varl; Это - превосходная основа для будущей разработки, которая, кроме всего прочего, включает шаблоны для всех четырех вызовов методов. В этом разделе рассмотрим пример создания аналога агрегирующей функции PRODUCT, которая является такой же, как функция SUM, но в ней вместо сложения выполняется умножение. Как и в функции SUM, в функции PRODUCT будут игнорироваться NULL-значения (если же все сомножители представляют собой NULL-значения, то функция PRODUCT должна возвращать NULL-значение), но в случае появления в исходных данных NULL-значений будут вырабатываться предупреждающие сообщения для пользователя о том, что таковые значения обнаружены и проигнорированы. Вначале нам необходимо внести некоторые простые модификации. Прежде всего присвоим классу имя Product вместо имени ExampleAggregate, присвоенного первоначально в связи с тем, что так был назван проект. Кроме того, необходимо объявить некоторые переменные-члены для хранения накапливаемого значения и значений некоторых флажков. using System; using System.Data; using System.Data.SqlClient; using System.Data.SqlTypes; using Microsoft.SqlServer.Server; [Serializable] [Microsoft.SqlServer.Server.SqlUserDefinedAggregate(Format.Native)] public struct Product private SqlDouble dAccumulator; private bool fContainsNull; private bool fAllNull; Переменная fContainsNull будет использоваться для получения информации о том, следует ли предупредить пользователя о том, что обнаружены какие-либо игнорируемые значения. Переменная fAllNull позволяет определить, что все полученные значения представляли собой NULL-значение; в этом случае предусмотрен возврат NULL-значения и в качестве результата. Затем необходимо инициализировать значения применяемых переменных-членов в ходе выполнения метода Init: public void InitО Инициализация флажков и накопительной переменной dAccumulator = 1; fContainsNull = false; fAllNull = true; Теперь мы можем создать основную накопительную функцию: public void Accumulate(SqlDouble Value) Это - основной участок кода. В нем могут быть реализованы применяемые алгоритмы вычислений. А в данном примере просто происходит умножение текущего значения накопительной переменной на новое входное значение. При обнаружении NULL-значения устанавливается флажок, указывающий на то, что распознана ситуация, связанная с появлением неопределенного значения. В результате этого полученные данные игнорируются и сохраняется значение, накопленное к данному моменту if (Value.IsNull) { fContainsNull = true; else { fAllNull = false; dAccumulator *= Value; Комментарии, приведенные в коде функции, позволяют получить практически полное представление о ее работе. Следует также отметить, что в функции необходимо обеспечить контроль над изменениями условий, обозначаемых флажками. Не считая этого, достаточно просто продолжать накапливать итог, умножая текущее значение (при условии, что оно не представляет собой NULL-значение) на существующее накопительное значение. На этом подготовка накопительной части функции полностью завершена, и мы можем заняться разработкой метода Merge, обеспечивающего объединение результатов, public void Merge(Product Group) В данном конкретном примере применяется достаточно простой способ объединения данных. Он предусматривает перемножение имеющегося значения и значений, полученных от всех прочих экземпляров класса Product if (Group.dAccumulator.IsNull) if (Group.fContainsNull) fContainsNull = true; if (!Group.fAllNull) fAllNull = false; dAccumulator *= dAccumulator; Применительно к данной конкретной функции реализация метода слияния по существу сводится лишь к использованию тех же проверок, которые осуществляются в функции Accumulate. Наконец, мы можем перейти к реализации метода Terminate, позволяющего завершить работу по накоплению итогового результата после того, как эта работа будет выполнена до конца: public SqlDouble Terminate() На этом вьшолнение работы заканчивается и происходит вывод результатов if (fAllNull) return SqlDouble.Null; else { SqlContext .Pipe. Send ( WARNING: Aggregate values exist and were ignored ); return dAccumulator; Вслед за окончанием описанной выше процедуры разработки мы можем приступить к компиляции кода и его выгрузке: CREATE ASSEMBLY ExampleAggregate FROM <solution path>\ExampleAggregate\bin\Debug\ExampleAggregate.dll После этого можно создать агрегируюхцую функцию. След)ет отметить, что для создания агрегирующих функций применяется другой синтаксис. Основная синтаксическая структура оператора создания агрегирующих функций приведена ниже. CREATE AGGREGATE [ <schema name> . ] <aggregate name> (@param name <input sqltype> ) RETURNS <return sqltype> EXTERNAL NAME <assembly name> [ .<class name> ] Итак, чтобы создать агрегирующую функцию на основе разработанной сборки, необходимо применить, допустим, такой оператор: CREATE AGGREGATE dbo.Product(©input float) RETURNS float EXTERNAL NAME ExampleAggregate.Product После этого мы можем осуществить проверку созданной функции. Для проведения такой проверки подготовим небольшой образец таблицы, которая включает перемножаемые данные и содержит группирующий столбец, предназначенный для того, чтобы можно бьыо проверить, как работает подготовленная нами агрегирующая функция в сочетании с конструкцией GROUP BY: CREATE TABLE ТеStAggregate (
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |