Вложенная вставка в SQL Server (инкапсулировать или не инкапсулировать) - PullRequest
0 голосов
/ 21 июля 2009

У меня общая дискуссия с одним из моих разработчиков о философии структурирования хранимых процедур TSQL.

Давайте сделаем пару предположений (чтобы избежать ответов типа «не помещайте бизнес-логику в SP» и т. Д.):

  1. Бизнес-логика может быть в ИП
  2. Нет стандартного скриптового слоя CRUD SP
  3. Сложные процедуры выполняются в одной области действия в SP
  4. Разрешен динамический SQL

По сути, мой коллега ударился головой о стену вложенных вставок SQL Server в SQL Server. Вы можете вкладывать их за пределы одного уровня.

т.е. :

  • PROC C вызывается PROC B, результаты которого вставлены в временная таблица #X и операции выполняется, а затем набор результатов вернулся

  • PROC B вызывается PROC A, результаты (наш оригинальный финальный выбор из PROC C + Преобразования) из которые вставляются во временную таблицу #Z и выполняются операции, а затем возвращается набор результатов

Это приводит к тому, что SQL Server выдает ошибку, в которой говорится, что вы не можете вкладывать вставки во временные таблицы.

Я согласен с этой логикой, если исходить из наших четырех исходных предпосылок, тогда было бы просто допустимо включить логику, выполняемую в PROC C, непосредственно в PROC B.

Однако мой коллега, будучи хорошим объектно-ориентированным инкапсулятором, считает, что благодаря инкапсуляции последней вложенной вставки код становится более понятным.

С другой стороны, я чувствую, что инкапсуляция кода в операции CRUD, в которых используются временные таблицы, в корне противоречит декларативному и процедурному подходу к управлению данными, присущему SQL и реляционным базам данных.

В конечном счете, его аргумент заключается в том, что если бы логика была просто в одном SP, то в случае изменения схемы таблицы все SP, обращающиеся к таблице, должны были бы измениться. Тем не менее, я считаю, что это маловероятно, поскольку после того, как наша разработка уложит в свои столы, изменения не будут изменены.

Мой аргумент заключается в том, что инкапсуляция вставок временной таблицы для использования во вложении n-й степени (если возможно - к счастью, это не так) приведет к случаю, когда все SP, которые вызывают эту инкапсулированную процедуру (или мы должны теперь называть это методом?) в любом случае придется повторно проверять в случае изменения централизованной инкапсулированной процедуры, поскольку, если ее выходные данные не совпадают, это может привести к разрыву в вызывающем родительском SP.

Полагаю, мой главный вопрос заключается в следующем: по сути, T-SQL - это декларативный, процедурный или императивный язык. На мой взгляд, это явно смесь -> полагаю, если бы мне пришлось создавать рецепт, я бы сказал:

10% декларативный (поскольку в принципе его декларативный) 70% процедурный (в нашем случае, когда бизнес-процессы в процессах) 20% императив (императивные конструкции существуют - особенно в более новых версиях SQL Server)


p.s. На данный момент он предлагает использовать параметр OUTPUT в вызове SP, а не:

вставить в #temp exec spInsertUpdateTable

У меня совершенно другая неприязнь к параметрам OUTPUT, но я полагаю, что это может сработать. Любые другие предложения?

Ответы [ 3 ]

2 голосов
/ 21 июля 2009

Не ответ, просто некоторые из моих идей:

Отдельные значения передаются обратно более эффективно через параметры OUTPUT, чем через наборы результатов. Однако значение уменьшается с увеличением числа возвращаемых значений.

В SQL 2008 вы можете передавать временные таблицы в качестве параметров. Хорошо, вам нужно выполнить много настроек, чтобы включить это, но даже в этом случае это может стоить усилий, так как вы получите N уровней вложенных вызовов.

Легко поддерживаемый код - это святой Грааль, к которому мы все должны стремиться, поскольку - если есть какая-то справедливость - человек, который поддерживает код, должен быть его первоначальным создателем. [Вставьте шутку доктора Франкенштина здесь.] Это должно подчеркнуть преимущества модульного кода («подпроцедуры»); если вам нужно только изменить одну вложенную процедуру, и вам не нужно изменять входы или выходы, то вам не нужно беспокоиться (т.е. рефакторинг) о процедурах, которые вызывают или вызываются ею.

Что касается декларативного, процедурного и императивного, извините, с колледжа прошли годы, и я слишком долго пробыл в окопах, чтобы обсуждать теории с высоким содержанием флютина, не работая в течение часа. *

1 голос
/ 22 июля 2009

Если вы все еще используете SQL Server 2000, я рекомендую прочитать эту статью базы знаний: http://support.microsoft.com/kb/243586/.

Раздел: «Перекомпиляции из-за определенных операций с временными таблицами Использование временных таблиц в хранимой процедуре может привести к перекомпиляции хранимой процедуры при каждом ее выполнении.

Чтобы избежать этого, измените хранимую процедуру так, чтобы она соответствовала следующим требованиям: Все операторы, которые содержат имя временной таблицы, ссылаются на временную таблицу, созданную в той же хранимой процедуре, но не в вызывающей или вызываемой хранимой процедуре или в строке, выполняемой с использованием инструкции EXECUTE или хранимой процедуры sp_executesql. "

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

1 голос
/ 22 июля 2009

Я думаю, что, возможно, этого следует избегать вместо ответа на вопрос, но первое, что я хотел бы сделать, это изучить, почему существуют все эти временные таблицы, которые нужно обойти. Чаще всего правильно построенный оператор выбора, вставки или обновления может заменить группы временных таблиц. Это на самом деле цель T-SQL - иметь возможность написать одну инструкцию для действия на весь набор. Поэтому, когда вы говорите «+ преобразования», я сразу перехожу к «ах, реорганизуйте эти временные таблицы прямо из решения, сделав выбор, который делает преобразования». Имеет смысл?

Пример: посмотрите, можете ли вы получить желаемый результат с двумя вложенными представлениями вместо сохраненных процедур. Нет проблем с передачей результатов между представлениями (в любом случае, это немного неправильно). Плюс, вы получаете оптимизацию запросов по всей операции (SQL Server расширит определения представления и оптимизирует все сразу)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...