Программирование >>  Программирование баз данных 

1 ... 108 109 110 [ 111 ] 112 113 114 ... 346


EXECUTE ({<string variable><literal command string> })

Как и при вызове на выполнение хранимых процедур, допускается использовать и то и другое ключевое слово (EXEC и EXECUTE).

Рассмотрим применение динамических запросов на примере базы данньгх AdventureWorks. Для этого создадим фиктивную таблицу, из которой будет осуществляться динамическая выборка информации:

USE AdventureWorks GO

Создание таблицы, в которой будет представлена информация -- для динамического кода SQL CREATE TABLE DynamicSQLExample (

TablelD int IDENTITY NOT NULL

CONSTRAINT PKDynamicSQLExample PRIMARY KEY, SchemaName varchar(128) NOT NULL,

TableName varchar(128) NOT NULL

/* Заполнение таблицы. На этот раз используются данные обо всех пользовательских ** таблицах в базе данных

INSERT INTO DynamicSQLExample

SELECT s.name AS SchemaName, t.name AS TableName FROM sys.schemas s JOIN sys.tables t ON s.schema id = t.schema id

Выполнение этого сценария должно привести к получению примерно таких результатов:

(75 row(s) affected)

Рассматривая полученные результаты, следует помнить традиционную оговорку рек-ламщиков: Фактически результаты могут оказаться немного инымиИначе говоря, состав полученных результатов зависит от того, какие примеры из книги были вами выполнены, какие вы пропустили и в отношении каких таблиц проявили инициативу, уничтожив следы выполнения упражнений после их завершения. Так или иначе, вышеназванные различия не имеют особого значения.

Итак, на данный момент сформирован список всех таблиц в текущей базе данных. Теперь предположим, что требуется обеспечить выборку некоторых данных, хранящихся в одной из таблиц, но таблица должна быть указана только на этапе прогона с помощью ее идентификатора. Например, выборка всех данньгх из таблицы с идентификатором 13 может быть выполнена следующим образом:

DECLARE ©SchemaName varchar(128)

DECLARE ©TableName varchar(128)

-- Определить имя таблицы, имеющей указанный идентификатор SELECT ©SchemaName = SchemaName, ©TableName = TableName

FROM DynamicSQLExample

WHERE TablelD = 13

-- Наконец, это значение передается в оператор EXEC EXEC (SELECT * FROM + ©SchemaName + . + ©TableName)



Если имена таблиц, собранные в таблице DynamicSQLExample при выполнении этого упражнения читателем, совпадают с именами, полученными автором, то идентификатор TablelD, равный 13, должен соответствовать таблице Categories. В этом случае должны быть получены примерно такие результаты, как показано в табл. 10.2 (в целях сокращения объема таблицы правые столбцы были исключены).

Таблица 10.2. Результаты выполнения динамически сформированного кода SQL

VendorlD AccoiintNuxnber Name

1 INTERNATOOOl International

2 electron0002 Electronic Bike Repair & Supplies

3 PREMIEROOOl Premier Sport, Inc.

4 COMFORTOOOl Comfort Road Bicycles

Нарушения в работе оператора exec

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

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

Оператор EXEC выполняется в том же контексте защиты, в котором работает текущий пользователь, а не в контексте защиты вызывающего объекта.

Оператор EXEC выполняется в том же контексте соединения и транзакцион-ном контексте, что и вызывающий объект (дополнительная информация на эту тему приведена в главе 12).

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

EXEC не может использоваться в пользовательской функции.

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

Домен, в котором действует оператор exec

Принципы, на основании которых устанавливается область определения переменных в операторе EXEC, с трудом поддаются пониманию. Но фактически строка с оператором, в которой происходит вызов оператора EXEC, имеет ту же область



определения, что и остальная часть пакета (или процедуры), в котором выполняется оператор EXEC, хотя код, вызываемый на выполнение в результате применения оператора EXEC, рассматривается как принадлежащий к отдельному пакету. Поскольку такая ситуация встречается часто, проще всего показать ее на примере: USE AdventureWorks

/* Вначале объявляются переменные. Одна из них предназначена для хранения данных, ** передаваемых в оператор EXEC, а другая - для получения возвращаемых данных (но ** в данном случае возврат не происходит) */

DECLARE @InVar varchar(50) DECLARE ©OutVar varchar(50)

-- Подготовка строки, предназначенной для передачи в команду EXEC SET ©InVar = SELECT ©OutVar = FirstName FROM Person.Contact WHERE ContactID = 1

-- Выполнение команды EXEC (©Invar)

-- Теперь, чтобы убедиться в том. что результат от этого не зависит, вызовем --на выполнение оператор SELECT непосредственно, без использования -- переменной ©InVar

EXEC (SELECT ©OutVar = FirstName FROM Person.Contact WHERE ContactID =1)

-- Переменная ©OutVar будет по-прежнему иметь NULL-значение, поскольку в нее не -- удается поместить какие-либо данные SELECT ©OutVar

Теперь рассмотрим полученные результаты:

Msg 137, Level 15, State 1, Line 1

Must declare the scalar variable ©OutVar.

Msg 137, Level 15, State 1, Line 1

Must declare the scalar variable ©OutVar.

NULL

(1 row(s) affected)

Очевидно, что СУБД SQL Server сразу же сообщает об ошибке и не может предпринять каких-либо дальнейших действий. Но следует пояснить, почему получено сообщение об ошибке, указывающее на отсутствие объявления, Must Declare , тогда как переменная ©OutVar уже объявлена. Безусловно, эта переменная объявлена во внешней области определения, но не в самом операторе EXEC.

Рассмотрим, что произойдет, если тот же сценарий будет организован несколько иначе:

USE AdventureWorks

-- На этот раз требуется только одна переменная, но потребность в ней сохраняется -- в течение более продолжительного времени DECLARE ©InVar varchar(200)

/* Подготовка строки для передачи в команду EXEC. На этот раз предпринимается ** попытка передать одновременно несколько операторов. Все эти операторы ** выполняются в виде одного пакета */

SET ©InVar = DECLARE ©OutVar varchar(50)

SELECT ©OutVar = FirstName FROM Person.Contact

WHERE ContactID = 1 SELECT The Value Is + ©OutVar



1 ... 108 109 110 [ 111 ] 112 113 114 ... 346

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика