|
Программирование >> Программирование баз данных
РК int NOT NULL PRIMARY KEY, GroupKey int NOT NULL, Value float NOT NULL Теперь нам достаточно лишь ввести в таблицу определенный объем данных, применяемых в ходе проверки: INSERT INTO TestAggregate(PK, GroupKey, Value) VALUES (1, 1, 2) INSERT INTO TestAggregate(PK, GroupKey, Value) VALUES (2, 1, 6) INSERT INTO TestAggregate(PK, GroupKey, Value) VALUES (3, 1, 1.5) INSERT INTO TestAggregate(PK, GroupKey, Value) VALUES (4, 2, 2) INSERT INTO TestAggregate(PK, GroupKey, Value) VALUES (5, 2, 6) Этого достаточно для того, чтобы приступить к тестированию агрегирующей функции. Предположим, что задание состоит в получении с помощью функции PRODUCT произведений по данным всех строк, относящихся к каждой группе (в образце данных содержатся две группы, поэтому в итоге должны быть получены две строки): SELECT GroupKey, dbo.Product(Value) AS Product FROM TestAggregate GROUP BY GroupKey После вызова приведенного выше оператора на выполнение происходит возврат двух строк (как и следовало ожидать): GroupKey Product 1 18 2 12 (2 row(s) affected) Проверьте полученные результаты по применяемому образцу данных и убедитесь в том, что они соответствуют действительности. Многие разработчики, ознакомившись с возможностями создания агрегирующих функций, выражают сомнение в тюм, чтю им придетея достеьтючно частю пользоваться такими возможностями. В действительности большинство разработчиков никогда не сталкиваются с ситуацией, в которой возникает подобная необходимость. Тем не менее следует помнить, что побудительным стимулом для включения все новых и новых программных средств в состав инструментальных средств разработчика являются прежде всего потребности практики. Агрегирующие функции не составляют в этом исключения. Потребность в создании таких функций возникает редко, но подобные ситуации характерны также тем, что в них действительно не может применяться какая-либо иная программная конструкция. Иными словами, автор подготовил данный раздел не с той целью, чтобы читатель обязательно изучил в нем и запомнил каждый нюанс. Однако изложенная здесь информация позволяет получить полное представление о возможностях и устройстве агрегирующих функций, а в случае необходимости послужит надежной отправной тачкой для глубокого освоения этой тематики. Создание триггеров на основе сборок На основе сборок могут создаваться не только те программные объекты, которые были описаны выше в данной главе, но и триггеры, причем сборки, применяемые для создания триггеров, во многом напоминают сборки любых других типов, но характеризуются наличием небольших, но важных отличительных особенностей. Отличительные особенности, обусловленные спецификой триггеров как программных объектов, описаны ниже. Функционирование триггеров зависит от контекста, в котором они активизированы. Иными словами, триггеры должны действовать по-разному, в зависимости от того, происходит ли их вызов в условиях применения операций INSERT (вставка), UPDATE (обновление) или DELETE (удаление). В зависимости от типов триггеров в них по-разному происходит обработка таблиц inserted и deleted. В предьщущих главах речь уже шла о том, что иногда возникает необходимость определить контекст текущего соединения; это требуется для получения доступа к различным интересующим нас объектам. Но в этом контексте может также содержаться информация об условиях активизации курсора; например, объект SqlContext, который применялся для получения контекста соединения во многих рассматривавшихся ранее примерах, может содержать также объект SqlTriggerContext, позволяющий определить значения свойств, на основании которых можно узнать, происходит ли в данный момент операция обновления или удаления (о чем шла речь применительно к первой особенности сборок, поддерживающих триггеры). Возможность получения доступа к текущим соединениям обусловливает также возможность получения доступа к таблицам триггера inserted и deleted, для чего достаточно просто выполнить запрос к этим таблицам. Рассмотрим описанные выше особенности сборок, предназначенных для создания курсоров, на примере. Начнем с создания нового проекта SQL Server в программе Visual Studio (на этот раз автор решил присвоить разрабатываемому проекту имя ExampleTrigger). После того как проект будет создан, щелкните правой кнопкой мыши на обозначении проекта в окне Solution Explorer и выберите команду Add=>Trigger... . Программа Visual Studio настолько успешно решает задачу формирования нового проекта создания триггера, что предлагаемый ею шаблон практически полностью готов к работе. В действительности автоматически подготовленный в программе Visual Studio код можно было бы непосредственно вызывать на вьшолнение, если бы в нем не было одного недостатка: using System; using System.Data; using System.Data.SqlClient; using Microsoft.SqlServer.Server; public partial class Triggers Раскомментируйте следующую строку и введите в качестве значения параметра Target имя существующей таблицы или представления [Microsoft.SqlServer.Server.SqlTrigger (Name= ExampleTrigger , Target= Tablei , Event= FOR UPDATE )] public static void ExampleTrigger() в этом месте может быть вставлен другой код SqlContext.Pipe.Send( Trigger FIRED ); Эта важная строка кода, о которой идет речь, еще раз приведена ниже. Проблема заключается в том, что в СУБД SQL Server должна быть передана более подробная информация о том, какие действия должны выполняться с объектами другрк типов. В частности, необходимо )тсазать, применительно к какой таблице и при каких событиях должен активизироваться разрабатьшаемый тррптер. Фактически нам необходимо подготовить специальную демонстрационную таблицу, чтобы решить указанную задачу, поскольку лишь после этого мы сможем реально ввести триггер в действие, поэтому на данном этапе создадим такую таблицу и присвоим ей имя Trigger Table: [Microsoft.SqlServer.Server.SqlTrigger (Name= ExampleTrigger , Target= TriggerTable , Event= FOR INSERT, UPDATE, DELETE )] Обратите внимание на то, что в этот код внесены также изменения в ту часть, которая касается событий, вызывающих активизацию триггера, и включены все типы событий. Теперь мы можем внести небольшие изменения в тело функции, чтобы проще было продемонстрировать различные действия, выполняемые с помощью триггера, а также, что еще более важно, похсазать, как проверить контекст активизации и выполнить действия, соответств)тощие тем операциям, которые применяются к рассматриваемой таблице. Начнем этот процесс внесения модификаций с создания определения icjiacca: public static void ExampleTrigger() Получить дескриптор текущего соединения SqlConnection cn = new SqlConnection( context connection=true ); cn.OpenO ; SqlTriggerContext ctxt = SqlContext.TriggerContext; SqlCommand cmd = new SqlCommandO; cmd.Connection = cn; Ha данный момент существенные изменения по сравнению с тем кодом, который рассматривался в других примерах применения инфраструктуры .NET, не наблюдаются. Возможно, единственным сутцественным отличием по сравнению с другими примерами кода является применение объекта SqlTriggerContext; этот объект будет служить нам в дальнейшем для определения того, какое действие вызвало активизацию триггера. Итак, мы можем приступить к написанию кода, вызов которого осуществляется в зависимости от того, какое действие привело к активизации триггера (в проверке условия вызова кода участвует свойство TriggerAction объекта TriggerContext из контекста SqlContext). Для этого предусмотрено применение простой команды switcli (безусловно, многие опытные программисты возражают против использования оператора switcli, но в данном случае реализация этой программной констр)тс-ции не приводит к каким-либо отрицательным последствиям). Кроме того, в коде должна быть предусмотрена передача различных сообщений пользователю, чтобы он мог следить за тем, что происходит. Но на практике вывод какой-либо информации из кода триггера не рекомендуется, поскольку, вообще говоря, триггер должен осуществлять свои действия незаметно для пользователя. Итак, автор реализовал свой замысел и предусмотрел вывод нескольких сообщений в рассматриваемом примере лишь для того, чтобы иметь полную информацию о том, какие действия выполняются триггером в каждой ситуации.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |