EXECUTE (Transact-SQL)

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

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

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

В 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 длина символьной строки была ограничена 8 000 байт. Это требовало динамического объединения длинных строк во время выполнения. В SQL Server можно указать тип данных varchar(max) или nvarchar(max), который позволяет символьным строкам содержать до 2 ГБ данных.

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

USE master; EXEC ('USE AdventureWorks2008R2; SELECT BusinessEntityID, JobTitle 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, предложение (Transact-SQL).

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

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

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

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

Примеры

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

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

USE AdventureWorks2008R2;
GO
EXEC dbo.uspGetEmployeeManagers 6;
GO

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

EXEC dbo.uspGetEmployeeManagers @BusinessEntityID = 6;
GO

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

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

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

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

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

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

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

USE AdventureWorks2008R2;
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.AdventureWorks2008R2.dbo.uspGetEmployeeManagers @BusinessEntityID = 6;

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

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

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

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

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

USE AdventureWorks2008R2;
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 AdventureWorks2008R2.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 AdventureWorks2008R2;
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 AdventureWorks2008R2;
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 AdventureWorks2008R2.Production.Product
    WHERE ProductID = ? ', 952) AT SeattleSales;
GO