|
По материалам статьи Robert Marda на сайте sqlservercentral.com: When to Use Dynamic SQL Динамический SQL запрос - это некоторый код, который создаётся и сохраняется в переменной, пока не возникнет необходимость его выполнения. Большинство DBA и разработчиков предпочитают не использовать динамические SQL запросы по целому ряду причин. Среди наиболее типичных таких причин то, что план выполнения динамического запроса не будет кэшироваться и то, что безопасность должна устанавливаться другими способами. Тем не менее, автор использует динамические запросы всякий раз, когда, считает, что это лучший способ получения результата, и твёрдо полает, что для динамических запросов есть место почти в каждой базе данных. Таблицы, необходимые для демонстрационных примеров С помощью представленных ниже скриптов, можно создать необходимые для демонстрационных примеров таблицы и заполнит их данными: CREATE TABLE #ColumnNames (ColumnID int IDENTITY (1, 1) NOT NULL, ColumnName varchar (50) NULL) Пример №1 Этот первый пример показывает, как получить ColumnName из существующей таблицы и использовать это, как алиас для столбца, который содержит соответствующие данные. Это одно из возможных решений, с помощью которого можно предоставить возможность пользователям создавать их собственные столбцы и заполнять их значениями посредством обычной вставки в обе таблицы. В реальных применениях используются не временные таблицы, как в этом примере. Если Вы решите предоставить возможность пользователям выполнять подобные операции, единственным способом возвращения им требуемых результирующих наборов, будет использование ColumnName в динамическом запросе. В примере представлено одно из возможных решений, с помощью которого Вы можете решить описанную выше задачу: DECLARE @Query varchar(300), @ColumnName varchar(50) Представленный в примере алгоритм полезен, когда Вы хотите передать результат, установленного кем - то значения, используя ColumnName добавленного пользователем столбца, по аналогии с электронной таблицей Excel. Пример №2 Представленный в предыдущем примере алгоритм для ColumnName также может быть применён и к именам таблиц TableName. Если Вам нужно в запросе или в хранимой процедуре получить данные об указанном в переменной имени таблицы, используйте нижеследующий алгоритм: DECLARE @Query varchar(300), @TableName varchar(30) Строки, выводимые PRINT, продемонстрируют результат работы алгоритма. Пример №3 Довольно часто для разграничения списка в переменной применяют запятую, когда необходимо использовать ключевое слово IN для ограничения результирующего набора. Подобный запрос может иметь следующий вид: DECLARE @InList varchar(30) Если Вы используете только одинарные цифры в переменной
@InList, представленный выше запрос будет работать. Конечно,
если будет использоваться эквивалентный признак для ключевого
слова IN. SQL сервер попытается конвертировать список в int,
что заработает только если в списке будет одинарные
цифры. DECLARE @InList varchar(30), @Query varchar(300) Строки, выводимые PRINT, используются только для демонстрации просмотра переменной @InList. Пример №4 Когда разграниченный запятыми список не является списком из чисел, необходимо будет внести небольшие коррективы, для учёта специфики такого списка: DECLARE @InList varchar(30) Если в SET @InList необходимо использовать значения 'yes' или "no", всё будет выполнено, как надо. Но, при использовании запятой, SQL сервер будет пытаться вычленять полную символьную строку, куда попадёт и запятая. Есть много способов разрешения этой проблемы, и все они, кроме одного, не используют динамический запрос. Рассмотрим метод с динамическим запросом: DECLARE @InList varchar(30), @Query varchar(300), @Position int В этом примере, WHILE LOOP используется для вычленения отдельного значения, необходимого для присвоения переменной @InList, используемой при формировании динамического запроса. Пример №5 Динамическое формирование большого запроса, основанного на значениях в различных переменных, это то, что вызывает чувство сомнения у большинства администраторов базы данных и разработчиков. Автор считает, что использование одного динамического запроса может заменить порой 10, 20 или более хранимых процедур и избавить от настройки эффективности их исполнения. В следующем примере Вы жертвуете эффективностью ради удобства разработки запроса: DECLARE @Query varchar(1000), @ClientName varchar(50), @ColumnName varchar (50), @ColumnDisplay tinyint, @Debug bit Этот пример очень показателен. Так как многие из Вас,
скорее всего, просто скопируют код примера, чтобы опробовать
его в действии, автор включил команды DROP TABLE, предвидя то,
что Вы можете захотеть изменить значения четырех переменных:
@ClientName, @ColumnName, @ColumnDisplay и @Debug. Это может
быть сделано, что бы увидеть, как подобные изменения
затрагивают структуру запроса. Можно добавить @Debug в запрос
и хранимую процедуру с динамическим запросом так, чтобы можно
было видеть, как они формируются, причём, без их изменения и с
гарантией, что они будут функционировать нормально для всех,
кто их будет использовать. @ColumnName = 'dealer' Заключение Есть задачи, когда динамический запрос является самым легким и, возможно, единственным решением и может исполняться также как статический запрос. Когда эффективность и быстродействие имеют высший приоритет, тогда Вы должны всячески избегать динамических запросов. |
Перевод: Александра Гладченко 2002г. |