Переместить SELECT на сторону SQL Server - PullRequest
1 голос
/ 02 января 2011

У меня есть триггер SQLCLR.Он содержит большой и грязный SELECT внутри, с такими частями, как:

(CASE WHEN EXISTS(SELECT * FROM INSERTED I WHERE I.ID = R.ID)
THEN '1' ELSE '0' END) AS IsUpdated -- Is selected row just added?

, а также JOIN и т. Д. Мне нравится иметь результат в виде одной таблицы со всеми включенными.

Вопрос 1 .Могу ли я переместить этот SELECT на сторону SQL Server?Если да, как это сделать?

Говоря "переместить", я имею в виду создание хранимой процедуры или чего-то еще, что можно выполнить перед чтением набора данных в цикле while.

2 следующих вопросаимеет смысл, только если ответ «да».

Почему я хочу переместить SELECT?Во-первых, я не люблю смешивать SQL с кодом C #.Во-вторых, я предполагаю, что запросы на стороне сервера выполняются быстрее, поскольку у сервера больше шансов их кешировать.

Вопрос 2 .Я прав?Это какая-то оптимизация?

Кроме того, SELECT содержит константные строки, но они локализуемы.Например,

WHERE R.Status = "Enabled"

«Включено» должно быть изменено для французского, немецкого и т. Д. Итак, я хочу написать 2 статических метода - OnCreate и OnDestroy - а затем пометить их как хранимые процедуры.При регистрации / отмене регистрации моей сборки на стороне сервера просто вызывайте их соответственно.В формате OnCreate строка SELECT заменяет {0}, {1} ... требуемыми значениями из ресурсов сборки.Тогда я могу локализовать только ресурсы, а не каждый скрипт.

Вопрос 3 .Это хорошая идея?Существует ли существующий атрибут для обозначения методов, которые будут автоматически выполняться SQL Server после (не) регистрации сборки?

С уважением,

Ответы [ 3 ]

1 голос
/ 23 января 2011

Для начала, вам, вероятно, не нужно делать этот тип подзапроса внутри любого запроса, который вы делаете. В таблице INSERTED есть только строки, которые были обновлены (или вставлены, но мы можем предположить, что это триггер UPDATE, основанный на комментарии в вашем коде). Таким образом, вы можете либо INNER JOIN, и вы будете сопоставлять только строки в таблице с псевдонимом «R», или вы можете LEFT JOIN, и вы можете сказать, какие строки в R были обновлены, поскольку те, которые показывают NULL для всех столбцов, не были обновлены.

Вопрос 1) Как сказано ниже marc_s, триггер выполняется в контексте базы данных. Но это выходит за рамки этого. ВСЕ код, связанный с базой данных, включая SQLCLR, выполняется в базе данных. Здесь нет клиентской стороны. Это проблема, которая возникает у большинства людей с SQLCLR: он работает внутри контекста SQL Server. Что касается желания вызывать хранимый процесс из триггера: это можно сделать, НО таблицы INSERTED и DELETED существуют только в контексте самого триггера.

Вопрос 2) Похоже, что этот вопрос должен был начаться со слов «Также ВЫБРАТЬ». Здесь нужно учитывать две вещи. Во-первых, при проверке значений «Состояние» (или любых значений «Уточняющий запрос»), поскольку это не отображается для пользователя, следует использовать числовые значения. «Статус» «Включен» должен быть примерно таким, как «1», так что язык не имеет значения. Дополнительным преимуществом является то, что значения Status не только сохраняются, так как числа занимают намного меньше места, но и сравниваются намного быстрее. Во-вторых, любой текст, который должен отображаться пользователю, который должен быть чувствителен к языковым различиям, должен находиться в таблице, чтобы вы могли передать LanguageId или LocaleId, чтобы получить соответствующие строки для французского, немецкого и т. Д. Для отображения. Вы можете установить LocaleId пользователя или системы в целом в другой таблице.

Вопрос 3) Если под «регистрацией» вы имеете в виду, что сборка либо СОЗДАНА, либо УДАЛЕНА, вы можете перехватить эти события с помощью триггеров DDL. Вы можете посмотреть здесь некоторые основы:

http://msdn.microsoft.com/en-us/library/ms175941(v=SQL.90).aspx

Но CREATE ASSEMBLY и DROP ASSEMBLY - это события, которые можно отследить.

Если вы говорите о том, когда сборки загружаются и выгружаются из памяти, то я не знаю, как это перехватить.

1 голос
/ 02 января 2011

Ну, триггер SQL-CLR также будет выполнять на сервере внутри серверного процесса - так что это тоже на стороне сервера, здесь никакой пользы.

Но я согласен - триггеры должны быть записаны в T-SQL, когда это возможно, - нет особой пользы от наличия триггеров в C # .... вы можете показать весь код триггера ?? Если он не содержит действительно странных шаров, его довольно легко конвертировать в T-SQL.

Я не вижу, как вы могли бы "переместить" SELECT на сторону SQL и сохранить оставшуюся часть кода на C # - либо ваш триггер находится на T-SQL (мое предпочтение), либо на C # / SQL-CLR - я не думаю, что есть какой-либо способ «смешивать и сопоставлять».

0 голосов
/ 02 января 2011

Вопрос 1. http://www.sqlteam.com/article/stored-procedures-returning-data

Вопрос 3. Похоже, что нет подходящих атрибутов, по крайней мере в Пространстве имен Microsoft.SqlServer.Server .

...