Поделиться через


EXECUTE (Transact-SQL)

Выполняет командную строку — строку символов, в которой содержится пакет Transact-SQL или один из следующих модулей: системная хранимая процедура, пользовательская хранимая процедура, скалярная пользовательская функция или расширенная хранимая процедура.

Примечание по безопасностиПримечание по безопасности

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

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

Значок ссылки на разделСоглашения о синтаксисе в Transact-SQL

Синтаксис

Execute a stored procedure or function
[ { EXEC | EXECUTE } ]
    { 
      [ @return_status = ]
      { module_name [ ;number ] | @module_name_var } 
        [ [ @parameter = ] { value 
                           | @variable [ OUTPUT ] 
                           | [ DEFAULT ] 
                           }
        ]
      [ ,...n ]
      [ WITH RECOMPILE ]
    }
[;]

Execute a character string
{ EXEC | EXECUTE } 
        ( { @string_variable | [ N ]'tsql_string' } [ + ...n ] )
    [ AS { LOGIN | USER } = ' name ' ]
[;]

Execute a pass-through command against a linked server
{ EXEC | EXECUTE }
        ( { @string_variable | [ N ] 'command_string [ ? ]' } [ + ...n ]
        [ { , { value | @variable [ OUTPUT ] } } [ ...n ] ]
        ) 
    [ AS { LOGIN | USER } = ' name ' ]
    [ AT linked_server_name ]
[;]

Аргументы

  • @return\_status
    Необязательная целочисленная переменная, в которой сохраняется состояние возврата из модуля. Этот аргумент должен быть объявлен в пакете, хранимой процедуре или функции, прежде чем его можно будет указать в инструкции EXECUTE.

    При вызове определяемой пользователем скалярной функции аргумент @return\_status может иметь любой скалярный тип данных.

  • module_name
    Полное или неполное имя вызываемой хранимой процедуры или скалярной пользовательской функции. Имена модулей должны соответствовать правилам построения идентификаторов. В именах расширенных хранимых процедур учитывается регистр, вне зависимости от параметров сортировки сервера.

    Допускается выполнение модуля, созданного в другой базе данных, если пользователь, выполняющий этот модуль, является его владельцем или имеет соответствующие разрешения на его выполнение в этой базе данных. Модуль может быть выполнен на другом сервере SQL Server, если пользователь, запускающий модуль на выполнение, имеет соответствующие разрешения на этом сервере (удаленный доступ) и на выполнение модуля в этой базе данных. Если указано имя сервера, а имя базы данных не указано, компонент SQL Server Database Engine ищет модуль в базе данных пользователя по умолчанию.

  • ; number
    Необязательный целочисленный аргумент, используемый для группирования одноименных процедур. Этот аргумент не предназначен для расширенных хранимых процедур.

    ПримечаниеПримечание

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

    Дополнительные сведения о группах процедур см. в разделе CREATE PROCEDURE (Transact-SQL).

  • @module\_name\_var
    Имя локально определенной переменной, которая содержит имя модуля.

  • @parameter
    Аргумент для модуля с именем module_name, как определено в модуле. Имена аргументов должны предваряться символом (@). Если используется форма @parameter\_name=value, то имена аргументов и констант могут указываться не в том порядке, в котором они определены в модуле. Однако, если какой-либо из аргументов указывается в форме @parameter\_name=value, то в этой же форме должны быть указаны и все последующие аргументы.

    По умолчанию аргументы могут принимать значение NULL.

  • value
    Значение аргумента, передаваемое модулю или транзитной команде. Если имена аргументов не указаны, значения аргументов должны указываться в том же порядке, в каком они определены в модуле.

    При выполнении транзитных команд для связанных серверов порядок значений аргументов зависит от поставщика OLE DB связанного сервера. Большинство поставщиков OLE DB привязывают значения к аргументам слева направо.

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

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

    Значение по умолчанию может быть равно NULL. Как правило, действие, которое должно быть выполнено в этом случае, указывается в определении модуля.

  • @variable
    Переменная, в которой сохраняется или возвращается аргумент.

  • OUTPUT
    Указывает, что модуль или командная строка возвращает аргумент. Совпадающий аргумент модуля или командной строки также должен быть создан с ключевым словом OUTPUT. Это ключевое слово следует указывать для переменной курсора, если она передается в качестве аргумента.

    Если аргумент value определен как OUTPUT для модуля, выполняющегося на связанном сервере, любые изменения в соответствующем аргументе @parameter, произведенные поставщиком OLE DB, по окончании выполнения модуля будут скопированы обратно в переменную.

    Если значение, возвращаемое в аргументе OUTPUT, предполагается использовать в других инструкциях вызываемого пакета или модуля, это значение должно передаваться в виде переменной, то есть @parameter = @variable. Выполнить модуль, указав OUTPUT для аргумента, который не определен в модуле как OUTPUT, нельзя. Константы в качестве аргументов OUTPUT в модуль не передаются, а для возврата аргумента необходимо указывать имя переменной. Перед выполнением процедуры для переменной должен быть объявлен тип данных и присвоено значение.

    Если EXECUTE выполняет удаленную хранимую процедуру или транзитную команду к связанному серверу, то аргументы OUTPUT не могут иметь типы данных больших объектов (LOB).

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

  • DEFAULT
    Определяет значение аргумента по умолчанию, как определено в модуле. Если в модуле для аргумента не определено значения по умолчанию, а при вызове для этого аргумента ни значение, ни ключевое слово DEFAULT не указаны, выдается ошибка.

  • WITH RECOMPILE
    Инициирует перекомпиляцию нового плана, его использование и удаление после выполнения модуля. Если для модуля имеется существующий план запроса, то он остается в кэше.

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

    ПримечаниеПримечание

    Использовать параметр WITH RECOMPILE при вызове хранимой процедуры, для которой применяется синтаксис OPENDATASOURCE, нельзя. Параметр WITH RECOMPILE не учитывается при указании четырехкомпонентного имени объекта.

  • @string\_variable
    Имя локальной переменной. @Аргумент string_variable может иметь тип char, varchar, nchar или nvarchar. , в том числе с ключевым словом (max).

  • [N] 'tsql_string'
    Символьная константа. Аргумент tsql_string может иметь тип nvarchar или varchar. Если указано «N», строка интерпретируется как тип данных nvarchar.

  • AS <указание_контекста>
    Определяет контекст, в котором выполняется инструкция. Дополнительные сведения см. в разделе Основные сведения о контексте выполнения.

  • LOGIN
    Указывает, что воплощаемым контекстом является имя входа, область олицетворения — сервер.

  • USER
    Определяет, что контекст олицетворения — пользователь в текущей базе данных. Область олицетворения ограничена текущей базой данных. При переключении контекста на пользователя базы данных разрешения уровня сервера этого пользователя не наследуются.

    Важное примечаниеВажно!

    Пока активно переключение контекста на пользователя базы данных, любая попытка доступа к ресурсам за ее пределами вызовет ошибку выполнения инструкции. Это относится к инструкциям USE database, распределенным запросам, а также запросам, содержащим ссылки на другие базы данных по идентификаторам, состоящим из трех или четырех элементов. О том, как расширить область переключения контекста за пределы текущей базы данных, см. в разделе Расширение олицетворения базы данных с помощью инструкции EXECUTE AS.

  • 'name'
    Допустимое имя пользователя или имя входа. Аргумент name должен быть членом предопределенной роли сервера sysadmin или быть зарегистрирован в качестве участника в представлении sys.database_principals или sys.server_principals соответственно.

    В качестве аргумента name не может быть указана встроенная учетная запись (например NT AUTHORITY\LocalService, NT AUTHORITY\NetworkService или NT AUTHORITY\LocalSystem).

    Дополнительные сведения см. в разделе Определение пользователя или имени входа далее.

  • [N] 'command_string'
    Символьная константа, содержащая транзитную команду, передаваемую связанному серверу. Если указано «N», строка интерпретируется как nvarchar.

  • [?]
    Обозначает параметры, для которых задаются значения в списке <arg-list> сквозных команд, используемых в инструкции EXEC('…', <arg-list>) AT <linkedsrv>.

  • AT linked_server_name
    Указывает, что команда command_string выполняется на сервере linked_server_name, а результаты, если они есть, возвращаются клиенту. Аргумент linked_server_name должен указывать на существующее определение связанного сервера на локальном сервере. Определение связанного сервера производится при помощи хранимой процедуры sp_addlinkedserver.

Замечания

Аргументы могут указываться с помощью синтаксиса value или @parameter\_name = value. Аргументы не участвуют в транзакциях, поэтому при откате транзакции, в которой они были изменены, они не возвращаются в исходное значение. Возвращаемым значением всегда является то значение, которое существует на момент выхода из модуля.

Если модуль вызывает другой модуль, выполняет управляемый код модуля среды CLR, пользовательского типа или статистического выражения, возникает вложенность. Уровень вложенности увеличивается каждый раз, когда вызванный модуль или управляемый код начинает выполнение, и уменьшается при завершении его выполнения. Превышение максимальной вложенности (32 уровня) приводит к ошибке выполнения всей цепочки вызовов. Текущий уровень вложенности возвращает системная функция @@NESTLEVEL.

Поскольку удаленные хранимые процедуры и расширенные хранимые процедуры не входят в область транзакции (это не относится к транзакциям, начатым инструкцией BEGIN DISTRIBUTED TRANSACTION или при указании различных параметров конфигурации), осуществить откат команд, выполняемых через вызовы к ним, невозможно. Дополнительные сведения см. в разделах Системные хранимые процедуры (Transact-SQL) и BEGIN DISTRIBUTED TRANSACTION (Transact-SQL).

Если выполняется процедура, которая передает переменную типа cursor с размещенным в ней курсором, то возникает ошибка.

При выполнении модуля, начинающегося с инструкции, ключевое слово EXECUTE указывать не надо.

Выполнение хранимых процедур через EXECUTE

При выполнении хранимой процедуры, начинающейся с инструкции, ключевое слово EXECUTE указывать не надо.

Имена системных хранимых процедур SQL Server начинаются с символов «sp_». Физически они хранятся в базе данных Resource, но логически относятся к схеме sys любой системной или пользовательской базы данных. При выполнении системной расширенной хранимой процедуры (в пакете или в модуле, например в пользовательской хранимой процедуре или функции) рекомендуется предварять ее имя указанием схемы sys.

Имена системных расширенных хранимых процедур SQL Server начинаются с символов «xp_» и содержатся в схеме dbo базы данных master. При выполнении системной расширенной хранимой процедуры (в пакете или в модуле, например в пользовательской хранимой процедуре или функции) рекомендуется предварять ее имя указанием master.dbo.

При выполнении пользовательской хранимой процедуры (в пакете или в модуле, например в пользовательской хранимой процедуре или функции) рекомендуется предварять ее имя указанием схемы. Не рекомендуется давать пользовательским хранимым процедурам те же имена, что и системным. Дополнительные сведения о выполнении хранимых процедур см. в разделе Выполнение хранимых процедур (компонент Database Engine).

Указание в EXECUTE символьных строк

В предыдущих версиях SQL Server длина символьной строки была ограничена 8000 байт. Это требовало динамического объединения длинных строк во время выполнения. В SQL Server можно указать тип данных varchar(max) или nvarchar(max), который позволяет символьным строкам содержать до 2 ГБ данных.

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

USE master; EXEC ('USE AdventureWorks; SELECT EmployeeID, Title FROM HumanResources.Employee;');

Переключение контекста

Предложение AS { LOGIN | USER } = ' name ' переключает контекст выполнения динамической инструкции. Если переключение контекста указано в виде EXECUTE ('string') AS <context_specification>, его длительность ограничена областью действия запроса, в котором он выполняется. Дополнительные сведения см. в разделе Основные сведения о переключении контекста.

Указание имени пользователя или имени входа

Имя пользователя или имя входа, указанное в предложении AS { LOGIN | USER } = ' name ', должно присутствовать в качестве участника в представлении sys.database_principals или sys.server_principals соответственно, в противном случае инструкция завершится ошибкой. Кроме того, необходимы разрешения IMPERSONATE для этого участника. Если процедура вызывается не владельцем базы данных и не членом предопределенной роли сервера sysadmin, указанный участник должен существовать даже в том случае, если пользователь производит доступ к базе данных или экземпляру SQL Server в качестве члена группы Windows. Для примера рассмотрим следующие условия:

  • Группа CompanyDomain\SQLUsers имеет доступ к базе данных Sales.

  • Пользователь CompanyDomain\SqlUser1 является членом группы SQLUsers и, таким образом, неявно имеет доступ к базе данных Sales.

Несмотря на то, что пользователь CompanyDomain\SqlUser1 имеет доступ к базе данных как член группы SQLUsers, инструкция EXECUTE @string\_variable AS USER = 'CompanyDomain\SqlUser1' завершится ошибкой, так как пользователь CompanyDomain\SqlUser1 не существует в базе данных в качестве участника.

Рекомендация

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

Разрешения

На выполнение инструкции EXECUTE разрешения не требуются. Однако необходимы разрешения на защищаемые объекты, на которые ссылается командная строка в инструкции EXECUTE. Например, если строка содержит инструкцию INSERT, выполняющий инструкцию EXECUTE пользователь должен иметь разрешение INSERT на целевую таблицу. Разрешения проверяются в месте нахождения инструкции EXECUTE, даже если она содержится внутри модуля.

Разрешение EXECUTE на модуль по умолчанию имеет владелец модуля, который может передать его другим пользователям. При запуске модуля, выполняющего командную строку, разрешения проверяются в контексте того пользователя, который выполняет модуль, а не того, который его создал. Но в случае, если владельцем вызывающего и вызываемого модуля является один и тот же пользователь, проверка разрешений EXECUTE для второго модуля не выполняется. Дополнительные сведения см. в разделе Цепочки владения.

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

  • Модуль помечен как EXECUTE AS USER или SELF, и владелец модуля обладает соответствующими разрешениями на данный объект.

  • Модуль помечен как EXECUTE AS CALLER, и есть соответствующие разрешения на данный объект.

  • Модуль помечен как EXECUTE AS user_name и user_name имеет соответствующие разрешения на объект.

Разрешения для переключения контекста

Для выполнения EXECUTE AS с именем входа необходимо иметь разрешение IMPERSONATE на указанное имя входа. Для выполнения EXECUTE AS с пользователем базы данных необходимо разрешение IMPERSONATE на указанного пользователя. Если контекст выполнения не указан или указано EXECUTE AS CALLER, никакие разрешения IMPERSONATE не требуются.

Примеры

А. Вызов EXECUTE с передачей единственного аргумента

Хранимой процедуре uspGetEmployeeManagers требуется один аргумент (@EmployeeID). В следующем примере производится выполнение хранимой процедуры uspGetEmployeeManagers со значением 6 аргумента Employee ID 6.

USE AdventureWorks;
GO
EXEC dbo.uspGetEmployeeManagers 6;
GO

При выполнении переменная может быть явно поименована.

EXEC dbo.uspGetEmployeeManagers @EmployeeID = 6;
GO

Если приведенная инструкция является первой в пакете или сценарии osql или sqlcmd, то указание EXEC не требуется.

dbo.uspGetEmployeeManagers 6;
GO
--Or
dbo.uspGetEmployeeManagers @EmployeeID = 6;
GO

Б. Передача нескольких аргументов

В следующем примере выполняется хранимая процедура spGetWhereUsedProductID, которой передаются два аргумента: идентификатор продукта 819 и дата проверки @CheckDate, имеющая значение типа datetime.

USE AdventureWorks;
GO
DECLARE @CheckDate datetime;
SET @CheckDate = GETDATE();
EXEC dbo.uspGetWhereUsedProductID 819, @CheckDate;
GO

В. Указание tsql_string в EXECUTE

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

USE AdventureWorks;
GO
DECLARE tables_cursor CURSOR
   FOR
   SELECT s.name, t.name 
   FROM sys.objects AS t
   JOIN sys.schemas AS s ON s.schema_id = t.schema_id
   WHERE t.type = 'U';
OPEN tables_cursor;
DECLARE @schemaname sysname;
DECLARE @tablename sysname;
FETCH NEXT FROM tables_cursor INTO @schemaname, @tablename;
WHILE (@@FETCH_STATUS <> -1)
BEGIN;
   EXECUTE ('ALTER INDEX ALL ON ' + @schemaname + '.' + @tablename + ' REBUILD;');
   FETCH NEXT FROM tables_cursor INTO @schemaname, @tablename;
END;
PRINT 'The indexes on all tables have been rebuilt.';
CLOSE tables_cursor;
DEALLOCATE tables_cursor;
GO

Г. Выполнение удаленных хранимых процедур через инструкцию EXECUTE

В следующем примере производится выполнение хранимой процедуры uspGetEmployeeManagers на удаленном сервере SQLSERVER1 и сохранение возвращенного состояния выполнения в переменной @retstat.

DECLARE @retstat int;
EXECUTE @retstat = SQLSERVER1.AdventureWorks.dbo.uspGetEmployeeManagers @EmployeeID = 6;

Д. Использование в EXECUTE переменной хранимой процедуры

В следующем примере создается переменная, которая содержит имя хранимой процедуры.

DECLARE @proc_name varchar(30);
SET @proc_name = 'sys.sp_who';
EXEC @proc_name;

Е. Указание в EXECUTE ключевого слова DEFAULT

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

USE AdventureWorks;
GO
IF OBJECT_ID(N'dbo.ProcTestDefaults', N'P')IS NOT NULL
   DROP PROCEDURE dbo.ProcTestDefaults;
GO
-- Create the stored procedure.
CREATE PROCEDURE dbo.ProcTestDefaults (
@p1 smallint = 42, 
@p2 char(1), 
@p3 varchar(8) = 'CAR')
AS 
   SET NOCOUNT ON;
   SELECT @p1, @p2, @p3
;
GO

Хранимую процедуру Proc_Test_Defaults можно вызвать с разными сочетаниями параметров.

-- Specifying a value only for one parameter (@p2).
EXECUTE dbo.ProcTestDefaults @p2 = 'A';
-- Specifying a value for the first two parameters.
EXECUTE dbo.ProcTestDefaults 68, 'B';
-- Specifying a value for all three parameters.
EXECUTE dbo.ProcTestDefaults 68, 'C', 'House';
-- Using the DEFAULT keyword for the first parameter.
EXECUTE dbo.ProcTestDefaults @p1 = DEFAULT, @p2 = 'D';
-- Specifying the parameters in an order different from the order defined in the procedure.
EXECUTE dbo.ProcTestDefaults DEFAULT, @p3 = 'Local', @p2 = 'E';
-- Using the DEFAULT keyword for the first and third parameters.
EXECUTE dbo.ProcTestDefaults DEFAULT, 'H', DEFAULT;
EXECUTE dbo.ProcTestDefaults DEFAULT, 'I', @p3 = DEFAULT;

Ж. Указание AT linked_server_name в EXECUTE

В следующем примере командная строка передается удаленному серверу. Создается связанный сервер SeattleSales, который указывает на другой экземпляр SQL Server, а затем на нем выполняется инструкция DDL (CREATE TABLE).

EXEC sp_addlinkedserver 'SeattleSales', 'SQL Server'
GO
EXECUTE ( 'CREATE TABLE AdventureWorks.dbo.SalesTbl 
(SalesID int, SalesName varchar(10)) ; ' ) AT SeattleSales;
GO

З. EXECUTE с аргументом WITH RECOMPILE

В следующем примере производится выполнение хранимой процедуры Proc_Test_Defaults с компиляцией нового плана запроса, который после выполнения модуля удаляется.

EXECUTE dbo.Proc_Test_Defaults @p2 = 'A' WITH RECOMPILE;
GO

И. Выполнение пользовательской функции с помощью EXECUTE

Следующий пример показывает выполнение скалярной пользовательской функции ufnGetSalesOrderStatusText. Возвращенное значение сохраняется в переменной @returnstatus. Функции передается один входной аргумент @Status, который имеет тип данных tinyint.

USE AdventureWorks;
GO
DECLARE @returnstatus nvarchar(15);
SET @returnstatus = NULL;
EXEC @returnstatus = dbo.ufnGetSalesOrderStatusText @Status = 2;
PRINT @returnstatus;
GO

К. Применение EXECUTE для запроса к базе данных Oracle на связанном сервере

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

-- Setup the linked server.
EXEC sp_addlinkedserver  
        @server='ORACLE',
        @srvproduct='Oracle',
        @provider='OraOLEDB.Oracle', 
        @datasrc='ORACLE10';

EXEC sp_addlinkedsrvlogin 
    @rmtsrvname='ORACLE',
    @useself='false', 
    @locallogin=null, 
    @rmtuser='scott', 
    @rmtpassword='tiger';
 
EXEC sp_serveroption 'ORACLE', 'rpc out', true;
GO
 
-- Execute several statements on the linked Oracle server.
EXEC ( 'SELECT * FROM scott.emp') AT ORACLE;
GO
EXEC ( 'SELECT * FROM scott.emp WHERE MGR = ?', 7902) AT ORACLE;
GO
DECLARE @v INT; 
SET @v = 7902;
EXEC ( 'SELECT * FROM scott.emp WHERE MGR = ?', @v) AT ORACLE;
GO

Л. Переключение контекста на другого пользователя через EXECUTE AS USER

В следующем примере производится выполнение командной строки Transact-SQL, которая создает таблицу и указывает предложение AS USER для переключения контекста выполнения инструкции на пользователя User1. Компонент Database Engine при запуске инструкции проверяет разрешения, которыми обладает User1. User1 должен присутствовать в базе данных как пользователь и должен иметь разрешения на создание таблиц в схеме Sales; в противном случае инструкция завершается ошибкой.

USE AdventureWorks;
GO
EXECUTE ('CREATE TABLE Sales.SalesTable (SalesID int, SalesName varchar(10));')
AS USER = 'User1';
GO

М. Использование параметра с командами AT linked_server_name и EXECUTE

В следующем примере командная строка передается удаленному серверу со знаком вопроса (?) в качестве заполнителя для параметра. Пример создает связанный сервер SeattleSales, который указывает на другой экземпляр SQL Server, а затем выполняется инструкция SELECT по отношению к этому связанному серверу. Инструкция SELECT использует знак вопроса в качестве заполнителя для параметра ProductID (952), предоставляемого после инструкции.

-- Setup the linked server.
EXEC sp_addlinkedserver 'SeattleSales', 'SQL Server'
GO
-- Execute the SELECT statement.
EXECUTE ('SELECT ProductID, Name 
    FROM AdventureWorks.Production.Product
    WHERE ProductID = ? ', 952) AT SeattleSales;
GO