CREATE PROCEDURE (Transact-SQL)

Создает хранимую процедуру. Хранимая процедура — это сохраненная коллекция инструкций языка Transact-SQL или ссылка на метод среды CLR платформы Microsoft .NET Framework, которая может принимать и возвращать предоставленные пользователем параметры. Процедуры можно создавать для постоянного использования, для временного использования в одном сеансе (локальная временная процедура) или для временного использования во всех сеансах (глобальная временная процедура).

Хранимые процедуры могут выполняться автоматически при запуске экземпляра SQL Server.

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

Синтаксис

CREATE { PROC | PROCEDURE } [schema_name.] procedure_name [ ; number ] 
    [ { @parameter [ type_schema_name. ] data_type } 
        [ VARYING ] [ = default ] [ OUT | OUTPUT ] [READONLY]
    ] [ ,...n ] 
[ WITH <procedure_option> [ ,...n ] ]
[ FOR REPLICATION ] 
AS { <sql_statement> [;][ ...n ] | <method_specifier> }
[;]
<procedure_option> ::= 
    [ ENCRYPTION ]
    [ RECOMPILE ]
    [ EXECUTE AS Clause ]

<sql_statement> ::= 
{ [ BEGIN ] statements [ END ] }

<method_specifier> ::=
EXTERNAL NAME assembly_name.class_name.method_name

Аргументы

  • schema_name
    Имя схемы, которой принадлежит процедура.

  • procedure_name
    Имя новой хранимой процедуры. Имена процедур должны соответствовать правилам, предъявляемым к идентификаторам, и должны быть уникальными в схеме.

    В имена процедур настоятельно не рекомендуется включать префикс sp_. Этим префиксом в SQL Server обозначаются системные хранимые процедуры. Дополнительные сведения см. в разделе Создание хранимых процедур (компонент Database Engine).

    Локальную или глобальную процедуру можно создать, указав один символ номера (#) перед procedure_name (#procedure_name) в случае локальных временных процедур и два символа номера в случае глобальных временных процедур (##procedure_name). Присвоить временное имя хранимой процедуре CLR нельзя.

    Полное имя хранимой процедуры или глобальной временной хранимой процедуры не может включать более 128 символов (с учетом символов ##). Полное имя локальной временной хранимой процедуры с учетом символа # не может включать более 116 символов.

  • **;**number
    Необязательное целое число, используемое для группирования процедур с одним именем. Все сгруппированные процедуры можно удалить, выполнив одну инструкцию DROP PROCEDURE. Например, в приложении orders можно было бы использовать процедуры с именами orderproc;1, orderproc;2 и т. д. Инструкция DROP PROCEDURE orderproc удалила бы все процедуры из этой группы. Если имя содержит идентификаторы с разделителями, номер не должен быть частью идентификатора; следует выделять при помощи подходящего разделителя только procedure_name.

    На пронумерованные хранимые процедуры распространяются следующие ограничения.

    • В качестве типов данных для таких процедур нельзя использовать тип xml и определяемые пользователем типы данных среды CLR.

    • Для пронумерованной хранимой процедуры нельзя создать структуру плана.

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

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

  • **@**parameter
    Параметр процедуры. В инструкции CREATE PROCEDURE можно объявить один или более параметров. При выполнении процедуры значение каждого из объявленных параметров должно быть указано пользователем, если для параметра не определено значение по умолчанию или значение не задано равным другому параметру. Хранимая процедура может иметь не более 2 100 параметров. Если процедура содержит возвращающие табличное значение параметры, а в вызове отсутствует параметр, передается пустая таблица по умолчанию.

    Определяет имя параметра, используя знак @ как первый символ. Имя параметра должно соответствовать правилам для идентификаторов. Параметры являются локальными в пределах процедуры; в разных процедурах могут быть использованы одинаковые имена параметров. По умолчанию параметры могут использоваться только в качестве константных выражений; они не могут быть использованы вместо имен таблиц, столбцов или других объектов базы данных. Дополнительные сведения см. в разделе EXECUTE (Transact-SQL).

    Параметры не могут быть объявлены, если указан параметр FOR REPLICATION.

  • [ type_schema_name**.** ] data_type
    Тип данных параметра и схема, к которой он относится. Все типы данных, которые могут использоваться в качестве параметра хранимой процедуры Transact-SQL. Можно использовать определяемый пользователем табличный тип, чтобы объявить возвращающий табличное значение параметр в качестве параметра хранимой процедуры Transact-SQL. Возвращающие табличное значение параметры можно указать только в качестве входных параметров, и они должны сопровождаться ключевым словом READONLY. Тип данных cursor можно использовать только в качестве выходного параметра. При указании типа данных cursor нужно также указать ключевые слова VARYING и OUTPUT. Выходных параметров типа данных cursor может быть несколько.

    Параметры хранимых процедур CLR не могут иметь тип данных char, varchar, text, ntext, image, cursor, table и определяемый пользователем тип таблицы. Дополнительные сведения о соответствии между типами CLR и системными типами данных SQL Server см. в разделе Сопоставление данных о параметрах CLR. Дополнительные сведения о системных типах данных SQL Server и их синтаксисе см. в разделе Типы данных (Transact-SQL).

    Если тип параметра является определяемым пользователем типом данных CLR, то необходимо иметь связанное с этим типом разрешение EXECUTE.

    Если аргумент type_schema_name не указан, компонент SQL Server Database Engine ссылается на аргумент type_name в следующем порядке.

    • Системные типы данных SQL Server.

    • Установленная по умолчанию для текущего пользователя схема в текущей базе данных.

    • Схема dbo в текущей базе данных.

    В случае пронумерованных хранимых процедур типом данных не может быть тип xml или определяемый пользователем тип данных среды CLR.

  • VARYING
    Указывает результирующий набор, поддерживаемый в качестве выходного параметра. Этот параметр динамически формируется хранимой процедурой, и его содержимое может различаться. Применяется только к параметрам типа cursor.

  • default
    Значение параметра по умолчанию. Если значение default определено, процедуру можно выполнить без указания значения соответствующего параметра. Значение по умолчанию должно быть константой или может равняться NULL. Если в процедуре используется параметр с ключевым словом LIKE, он может включать символы-шаблоны %, _, [] и [^].

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

    Значения по умолчанию записываются в столбец sys.parameters.default только для процедур среды CLR. В случае параметров аргументов Transact-SQL этот столбец будет содержать значения NULL.

  • OUTPUT
    Показывает, что параметр процедуры является выходным. Значение этого параметра можно получить при помощи инструкции EXECUTE. Используйте параметры OUTPUT для возврата значений коду, вызвавшему процедуру. Параметры типов text, ntext и image не могут быть параметрами OUTPUT, если процедура не является процедурой CLR. Выходным аргументом с ключевым словом OUTPUT может быть заполнитель курсора, если процедура не является процедурой CLR. Определяемый пользователем табличный тип не может быть указан в качестве выходного параметра хранимой процедуры.

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

  • RECOMPILE
    Показывает, что компонент Database Engine не кэширует план выполнения процедуры и что процедура компилируется во время выполнения. Этот параметр нельзя использовать, если указан аргумент FOR REPLICATION. Задать параметр RECOMPILE для хранимой процедуры CLR нельзя.

    Чтобы компонент Database Engine удалил планы выполнения отдельных запросов в хранимой процедуре, следует использовать подсказку в запросе RECOMPILE. Дополнительные сведения см. в разделе Подсказки в запросах (Transact-SQL). Подсказку в запросе RECOMPILE следует использовать в тех случаях, когда необычные или временные значения используются только в подмножестве запросов, входящих в состав хранимой процедуры.

  • ENCRYPTION
    Показывает, что SQL Server выполнит затемнение исходного текста инструкции CREATE PROCEDURE. Результат затемнения не виден непосредственно ни в одном представлении каталога SQL Server. Пользователи, не имеющие доступа к системным таблицам или файлам баз данных, не смогут получить скрытый текст. Однако этот текст будет доступен привилегированным пользователям, которые либо смогут обращаться к системным таблицам через порт DAC, либо будут иметь непосредственный доступ к файлам баз данных. Кроме того, пользователи, имеющие право на подключение отладчика к серверному процессу, могут получить дешифрованный текст процедуры из памяти во время выполнения. Дополнительные сведения о доступе к системным метаданным см. в разделе Настройка видимости метаданных.

    Хранимыми процедурами CLR этот параметр не поддерживается.

    Процедуры, созданные с использованием этого параметра, не могут быть опубликованы при репликации SQL Server.

  • EXECUTE AS
    Определяет контекст безопасности, в котором должна быть выполнена хранимая процедура.

    Дополнительные сведения см. в разделе EXECUTE AS, предложение (Transact-SQL).

  • FOR REPLICATION
    Указывает, что хранимые процедуры, созданные для репликации, не могут выполняться на подписчике. Хранимая процедура, созданная с параметром FOR REPLICATION, используется как процедура-фильтр и выполняется только во время репликации. Если указан аргумент FOR REPLICATION, параметры не могут быть объявлены. Указать параметр FOR REPLICATION для хранимой процедуры CLR нельзя. Параметр RECOMPILE не учитывается для процедур, созданных с аргументом FOR REPLICATION.

    Процедура с параметром FOR REPLICATION будет иметь в представлении sys.objects и sys.procedures объектный тип RF.

  • <sql_statement>
    Одна или несколько инструкций языка Transact-SQL, которые будут включены в состав процедуры. При этом действуют некоторые ограничения, описанные в разделе «Примечания».

  • EXTERNAL NAME assembly_name**.class_name.method_name
    Метод сборки .NET Framework, на который должна ссылаться хранимая процедура CLR. Аргумент class_name должен быть допустимым идентификатором SQL Server и соответствовать существующему в сборке классу. Если имя класса включает названия пространств имен, отделенные точками (
    .), оно должно быть ограничено при помощи квадратных скобок ([]) или двойных кавычек (""**). Указанный метод класса должен быть статическим.

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

    По умолчанию SQL Server не производит выполнение кода CLR. Допускается создание, изменение и удаление объектов базы данных, содержащих ссылки на модули среды CLR, однако SQL Server их не выполняет до тех пор, пока не будет включен параметр clr enabled. Для включения этого параметра используйте хранимую процедуру sp_configure.

Замечания

Стандартный максимальный размер хранимой процедуры не установлен.

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

Инструкцию CREATE PROCEDURE нельзя объединять с другими инструкциями Transact-SQL в одном пакете.

По умолчанию параметры могут принимать значения NULL. Если параметр, имеющий значение NULL, используется в инструкции CREATE TABLE или ALTER TABLE при обращении к столбцу, не поддерживающему значения NULL, то компонент Database Engine возвращает ошибку. Чтобы предотвратить передачу значений NULL столбцу, который их не поддерживает, следует реализовать в процедуре соответствующую логику или передать столбцу значение по умолчанию при помощи ключевого слова DEFAULT инструкции CREATE TABLE или ALTER TABLE.

Для каждого столбца во временной таблице рекомендуется явно указывать атрибут NULL или NOT NULL. Если атрибуты NULL или NOT NULL не указаны в инструкции CREATE TABLE или ALTER TABLE, то способ назначения этих атрибутов столбцам компонентом Database Engine определяется параметрами ANSI_DFLT_ON и ANSI_DFLT_OFF. Если в контексте соединения выполняется хранимая процедура с настройками этих параметров, отличными от настроек соединения, в котором была создана процедура, столбцы таблицы, созданной для второго соединения, могут отличаться по признаку поддержки допустимости значений NULL и работать иначе. Если атрибут NULL или NOT NULL явно задан для каждого столбца, временные таблицы создаются с одним и тем же признаком поддержки допустимости значений NULL во всех соединениях, в которых выполняется хранимая процедура.

Использование параметров SET

При создании или изменении хранимой процедуры Transact-SQL компонент Database Engine сохраняет значения SET QUOTED_IDENTIFIER и SET ANSI_NULLS. Эти первоначальные значения используются при выполнении хранимой процедуры. Таким образом, пока хранимая процедура выполняется, любые значения SET QUOTED_IDENTIFIER и SET ANSI_NULLS, задаваемые во время клиентского сеанса, не учитываются. Другие параметры SET, такие как SET ARITHABORT, SET ANSI_WARNINGS или SET ANSI_PADDINGS, при создании или изменении хранимой процедуры не сохраняются. Если логика хранимой процедуры зависит от конкретного значения параметра, включите в начало процедуры инструкцию SET, чтобы гарантировать нужное значение. Если инструкция SET выполняется из хранимой процедуры, устанавливаемое ею значение действует только до завершения хранимой процедуры. После этого оно принимает прежнее значение, которое имело место при вызове хранимой процедуры. Это позволяет клиентам задавать нужные им параметры без влияния на логику хранимой процедуры.

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

Параметры ANSI_WARNINGS не годятся для передачи в хранимые процедуры, определяемые пользователем функции и при объявлении и установке переменных в пакетных инструкциях. Например, если объявить переменную типа char(3), а затем присвоить ей значение длиннее трех символов, данные будут усечены до размера переменной, а инструкция INSERT или UPDATE завершится без ошибок.

Использование параметров с хранимыми процедурами среды CLR

Параметры хранимой процедуры CLR могут иметь любой скалярный системный тип данных SQL Server.

Чтобы компонент Database Engine выбрал правильный вариант перегруженного метода .NET Framework, метод, указанный при помощи <квалификатора_метода>, должен иметь следующие характеристики.

  • Он должен быть объявлен как статический метод.

  • Он должен принимать то же количество параметров, что и процедура.

  • Метод не должен быть конструктором или деструктором класса.

  • Типы параметров метода должны быть совместимы с типами данных соответствующих параметров процедуры SQL Server. Сведения о совпадении типов данных SQL Server и .NET Framework см. в разделе Сопоставление данных о параметрах CLR.

  • Метод должен возвращать либо void, либо значение типа SQLInt32, SQLInt16, System.Int32 или System.Int16.

  • Если какой-либо параметр объявлен как OUTPUT, метод должен возвращать параметры по ссылке, а не по значению.

Получение информации о хранимых процедурах

Чтобы увидеть определение хранимой процедуры Transact-SQL, следует использовать представление каталога sys.sql_modules в базе данных, к которой относится процедура.

Например:

USE AdventureWorks;
GO
SELECT definition 
FROM sys.sql_modules 
JOIN sys.objects ON sys.sql_modules.object_id = sys.objects.object_id AND TYPE = 'P';
ПримечаниеПримечание

Текст хранимой процедуры, созданной с параметром ENCRYPTION, нельзя увидеть при помощи представления каталога sys.sql_modules.

Чтобы получить отчет об объектах, на которые ссылается процедура, нужно выполнить запрос к представлению каталога sys.sql_expression_dependencies или использовать функции sys.dm_sql_referenced_entities и sys.dm_sql_referencing_entities.

Для получения информации о хранимых процедурах CLR следует использовать представление каталога sys.assembly_modules в базе данных, к которой относится процедура.

Для получения информации о параметрах, определенных в хранимой процедуре, следует использовать представление каталога sys.parameters в базе данных, в которой находится процедура.

Отложенное разрешение имен

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

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

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

Если в хранимой процедуре предусмотрена обработка параметров, можно указывать значения параметров. Значение параметра может быть константой или переменной. Значением параметра не может быть имя функции. Переменные могут быть пользовательскими или системными переменными, например @@SPID.

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

При выполнении процедуры в первый раз она компилируется, при этом определяется оптимальный план получения данных. При последующих вызовах хранимой процедуры может быть повторно использован уже созданный план, если он еще находится в кэше планов компонента Database Engine. Дополнительные сведения см. в разделе Кэширование и повторное использование плана выполнения.

Параметры типа cursor

В хранимых процедурах Transact-SQL только параметры OUTPUT могут иметь тип cursor. Если параметр имеет тип данных cursor, он должен быть объявлен как VARYING и OUTPUT. Если параметр объявлен с ключевым словом VARYING, он должен иметь тип данных cursor и должно быть указано ключевое слово OUTPUT. Дополнительные сведения см. в разделе Использование типа данных cursor в параметре OUTPUT.

Временные хранимые процедуры

Компонент Database Engine поддерживает два типа временных процедур: локальные и глобальные. Локальная временная процедура видима только в контексте того соединения, в котором она была создана. Глобальная временная процедура доступна в контексте любого соединения. При завершении текущего сеанса локальные временные процедуры автоматически сбрасываются. Глобальная временная процедура сбрасывается при завершении последнего сеанса, в котором она использовалась. Дополнительные сведения см. в разделе Создание хранимых процедур (компонент Database Engine).

Автоматическое выполнение хранимых процедур

Хранимые процедуры могут выполняться автоматически при запуске SQL Server. Они должны быть созданы системным администратором в базе данных master и должны выполняться в контексте предопределенной роли сервера sysadmin в фоновом процессе. Они не могут иметь ни входных, ни выходных параметров. Дополнительные сведения см. в разделе Автоматическое выполнение хранимых процедур.

Вложенность хранимых процедур

Хранимые процедуры могут быть вложенными. Иными словами, одна хранимая процедура может вызывать другую. Уровень вложенности увеличивается на 1, когда начинается выполнение вызванной процедуры, и уменьшается на 1, когда вызванная процедура завершается. Уровень вложенности хранимых процедур может достигать 32. Дополнительные сведения см. в разделе Вложенные хранимые процедуры.

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

Имя объекта системного монитора

Имя счетчика системного монитора

SQLServer: кэш планов

Коэффициент попадания в кэш

 

Страницы кэша

 

Счетчик объектов в кэше*

* Эти счетчики доступны для разных категорий объектов кэша, включая нерегламентированные SQL-запросы, подготовленные SQL-запросы, процедуры, триггеры и т. д.

Дополнительные сведения см. в разделе SQL Server, объект Plan Cache.

Ограничения параметра <sql_statement>

Внутри хранимой процедуры может быть указана любая инструкция SET, за исключением SET SHOWPLAN_TEXT и SET SHOWPLAN_ALL. Эти инструкции могут встречаться только в пакете. Выбранный параметр SET остается в силе до завершения хранимой процедуры, после чего восстанавливается прежнее значение.

Если хранимую процедуру будут выполнять пользователи, не являющиеся ее владельцами, имена объектов, используемых внутри процедуры в любых инструкциях DDL, таких как CREATE, ALTER или DROP, инструкциях DBCC, EXECUTE и динамические инструкциях SQL должны быть дополнены именем схемы объекта. Дополнительные сведения см. в разделе Проектирование хранимых процедур (компонент Database Engine).

Разрешения

Для выполнения этой инструкции требуется разрешение CREATE PROCEDURE в отношении базы данных и разрешение ALTER в отношении схемы, в которой создается процедура.

Для выполнения хранимой процедуры CLR пользователь должен владеть сборкой, на которую ссылается <квалификатор_метода>, или иметь в отношении этой сборки разрешение REFERENCES.

Примеры

А. Использование простой процедуры

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

USE AdventureWorks;
GO
IF OBJECT_ID ( 'HumanResources.uspGetAllEmployees', 'P' ) IS NOT NULL 
    DROP PROCEDURE HumanResources.uspGetAllEmployees;
GO
CREATE PROCEDURE HumanResources.uspGetAllEmployees
AS
    SET NOCOUNT ON;
    SELECT LastName, FirstName, Department
    FROM HumanResources.vEmployeeDepartmentHistory;
GO

Хранимую процедуру uspGetEmployees можно выполнить следующим образом.

EXECUTE HumanResources.uspGetAllEmployees;
GO
-- Or
EXEC HumanResources.uspGetAllEmployees;
GO
-- Or, if this procedure is the first statement within a batch:
HumanResources.uspGetAllEmployees;

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

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

USE AdventureWorks;
GO
IF OBJECT_ID ( 'HumanResources.uspGetEmployees', 'P' ) IS NOT NULL 
    DROP PROCEDURE HumanResources.uspGetEmployees;
GO
CREATE PROCEDURE HumanResources.uspGetEmployees 
    @LastName nvarchar(50), 
    @FirstName nvarchar(50) 
AS 

    SET NOCOUNT ON;
    SELECT FirstName, LastName, Department
    FROM HumanResources.vEmployeeDepartmentHistory
    WHERE FirstName = @FirstName AND LastName = @LastName;
GO

Хранимую процедуру uspGetEmployees можно выполнить следующим образом.

EXECUTE HumanResources.uspGetEmployees N'Ackerman', N'Pilar';
-- Or
EXEC HumanResources.uspGetEmployees @LastName = N'Ackerman', @FirstName = N'Pilar';
GO
-- Or
EXECUTE HumanResources.uspGetEmployees @FirstName = N'Pilar', @LastName = N'Ackerman';
GO
-- Or, if this procedure is the first statement within a batch:
HumanResources.uspGetEmployees N'Ackerman', N'Pilar';

В. Использование простой процедуры с подстановочными параметрами

Следующая хранимая процедура возвращает сведения об указанных (по имени и фамилии) сотрудниках из представления. Извлекая информацию о сотрудниках, эта хранимая процедура сопоставляет ее с полученными параметрами; если параметры не предоставлены, то используется шаблон, заданный по умолчанию (фамилии, начинающиеся на букву D).

USE AdventureWorks;
GO
IF OBJECT_ID ( 'HumanResources.uspGetEmployees2', 'P' ) IS NOT NULL 
    DROP PROCEDURE HumanResources.uspGetEmployees2;
GO
CREATE PROCEDURE HumanResources.uspGetEmployees2 
    @LastName nvarchar(50) = N'D%', 
    @FirstName nvarchar(50) = N'%'
AS 
    SET NOCOUNT ON;
    SELECT FirstName, LastName, Department
    FROM HumanResources.vEmployeeDepartmentHistory
    WHERE FirstName LIKE @FirstName AND LastName LIKE @LastName;
GO

Хранимая процедура uspGetEmployees2может быть выполнена во многих сочетаниях. Ниже приведены только некоторые сочетания:

EXECUTE HumanResources.uspGetEmployees2;
-- Or
EXECUTE HumanResources.uspGetEmployees2 N'Wi%';
-- Or
EXECUTE HumanResources.uspGetEmployees2 @FirstName = N'%';
-- Or
EXECUTE HumanResources.uspGetEmployees2 N'[CK]ars[OE]n';
-- Or
EXECUTE HumanResources.uspGetEmployees2 N'Hesse', N'Stefen';
-- Or
EXECUTE HumanResources.uspGetEmployees2 N'H%', N'S%';

Г. Возвращение более чем одного результирующего набора

Следующая хранимая процедура возвращает два результирующих набора.

USE AdventureWorks;
GO
CREATE PROCEDURE uspNResults 
AS
SELECT COUNT(ContactID) FROM Person.Contact
SELECT COUNT(CustomerID) FROM Sales.Customer;
GO

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

Следующий пример создает хранимую процедуру uspGetList. Эта процедура возвращает список товаров, цена на которые не превышает указанный предел. Данный пример поясняет использование нескольких инструкций SELECT и нескольких параметров OUTPUT. Параметры OUTPUT предоставляют внешней процедуре, пакету или нескольким инструкциям Transact-SQL доступ к значениям, заданным во время выполнения процедуры.

USE AdventureWorks;
GO
IF OBJECT_ID ( 'Production.uspGetList', 'P' ) IS NOT NULL 
    DROP PROCEDURE Production.uspGetList;
GO
CREATE PROCEDURE Production.uspGetList @Product varchar(40) 
    , @MaxPrice money 
    , @ComparePrice money OUTPUT
    , @ListPrice money OUT
AS
    SET NOCOUNT ON;
    SELECT p.[Name] AS Product, p.ListPrice AS 'List Price'
    FROM Production.Product AS p
    JOIN Production.ProductSubcategory AS s 
      ON p.ProductSubcategoryID = s.ProductSubcategoryID
    WHERE s.[Name] LIKE @Product AND p.ListPrice < @MaxPrice;
-- Populate the output variable @ListPprice.
SET @ListPrice = (SELECT MAX(p.ListPrice)
        FROM Production.Product AS p
        JOIN  Production.ProductSubcategory AS s 
          ON p.ProductSubcategoryID = s.ProductSubcategoryID
        WHERE s.[Name] LIKE @Product AND p.ListPrice < @MaxPrice);
-- Populate the output variable @compareprice.
SET @ComparePrice = @MaxPrice;
GO

Процедура uspGetList возвращает из базы данных Adventure Works список товаров (велосипедов) стоимостью менее $700. Выходные (OUTPUT) параметры @Cost и @ComparePrices используются в языке выполнения управлением для вывода информации в окне Сообщения.

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

Переменная OUTPUT должна быть определена при создании процедуры и при использовании переменной. Имена параметра и переменной могут быть разными, однако типы данных и порядок расположения параметров должны совпадать, если только не используется конструкция @ListPrice= variable.

DECLARE @ComparePrice money, @Cost money 
EXECUTE Production.uspGetList '%Bikes%', 700, 
    @ComparePrice OUT, 
    @Cost OUTPUT
IF @Cost <= @ComparePrice 
BEGIN
    PRINT 'These products can be purchased for less than 
    $'+RTRIM(CAST(@ComparePrice AS varchar(20)))+'.'
END
ELSE
    PRINT 'The prices for all products in this category exceed 
    $'+ RTRIM(CAST(@ComparePrice AS varchar(20)))+'.'

Ниже приводится частичный результирующий набор:

Product                                            List Price
-------------------------------------------------- ------------------
Road-750 Black, 58                                 539.99
Mountain-500 Silver, 40                            564.99
Mountain-500 Silver, 42                            564.99
...
Road-750 Black, 48                                 539.99
Road-750 Black, 52                                 539.99

(14 row(s) affected)

These items can be purchased for less than $700.00.

Е. Использование параметра WITH RECOMPILE

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

USE AdventureWorks;
GO
IF OBJECT_ID ( 'dbo.uspProductByVendor', 'P' ) IS NOT NULL 
    DROP PROCEDURE dbo.uspProductByVendor;
GO
CREATE PROCEDURE dbo.uspProductByVendor @Name varchar(30) = '%'
WITH RECOMPILE
AS
    SET NOCOUNT ON;
    SELECT v.Name AS 'Vendor name', p.Name AS 'Product name'
    FROM Purchasing.Vendor AS v 
    JOIN Purchasing.ProductVendor AS pv 
      ON v.VendorID = pv.VendorID 
    JOIN Production.Product AS p 
      ON pv.ProductID = p.ProductID
    WHERE v.Name LIKE @Name;
GO

Ж. Использование параметра WITH ENCRYPTION

Следующий пример создает хранимую процедуру HumanResources.uspEncryptThis.

USE AdventureWorks;
GO
IF OBJECT_ID ( 'HumanResources.uspEncryptThis', 'P' ) IS NOT NULL 
    DROP PROCEDURE HumanResources.uspEncryptThis;
GO
CREATE PROCEDURE HumanResources.uspEncryptThis
WITH ENCRYPTION
AS
    SET NOCOUNT ON;
    SELECT EmployeeID, Title, NationalIDNumber, VacationHours, SickLeaveHours 
    FROM HumanResources.Employee;
GO

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

Выполнение хранимой процедуры sp_helptext:

EXEC sp_helptext 'HumanResources.uspEncryptThis';

Ниже приводится результирующий набор.

The text for object 'HumanResources.uspEncryptThis' is encrypted.

Непосредственный запрос данных из представления каталога sys.sql_modules:

USE AdventureWorks;
GO
SELECT definition FROM sys.sql_modules
WHERE object_id = OBJECT_ID('HumanResources.uspEncryptThis');

Ниже приводится результирующий набор.

definition
----------------------
NULL

(1 row(s) affected)

З. Использование отложенного разрешения имен

В следующем примере создается процедура uspProc1. В ней использовано отложенное разрешение имен. Эта хранимая процедура создается несмотря на то, что таблица, на которую она ссылается, не существует во время компиляции. Однако во время выполнения процедуры таблица должна существовать.

USE AdventureWorks;
GO
IF OBJECT_ID ( 'dbo.uspProc1', 'P' ) IS NOT NULL 
    DROP PROCEDURE dbo.uspProc1;
GO
CREATE PROCEDURE dbo.uspProc1
AS
    SET NOCOUNT ON;
    SELECT column1, column2 FROM table_does_not_exist
GO

Чтобы убедиться в том, что хранимая процедура создана, следует выполнить следующий запрос:

USE AdventureWorks;
GO
SELECT definition
FROM sys.sql_modules
WHERE object_id = OBJECT_ID('dbo.uspproc1');

Ниже приводится результирующий набор.

definition
-----------------------------------------------------------------------
CREATE PROCEDURE uspproc1
AS
    SELECT column1, column2 FROM table_does_not_exist

(1 row(s) affected)

И. Использование предложения EXECUTE AS

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

USE AdventureWorks;
GO
IF OBJECT_ID ( 'Purchasing.uspVendorAllInfo', 'P' ) IS NOT NULL 
    DROP PROCEDURE Purchasing.uspVendorAllInfo;
GO
CREATE PROCEDURE Purchasing.uspVendorAllInfo
WITH EXECUTE AS CALLER
AS
    SET NOCOUNT ON;
    SELECT v.Name AS Vendor, p.Name AS 'Product name', 
      v.CreditRating AS 'Credit Rating', 
      v.ActiveFlag AS Availability
    FROM Purchasing.Vendor v 
    INNER JOIN Purchasing.ProductVendor pv
      ON v.VendorID = pv.VendorID 
    INNER JOIN Production.Product p
      ON pv.ProductID = p.ProductID 
    ORDER BY v.Name ASC;
GO

К. Создание хранимой процедуры CLR

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

CREATE ASSEMBLY HandlingLOBUsingCLR
FROM '\\MachineName\HandlingLOBUsingCLR\bin\Debug\HandlingLOBUsingCLR.dll';
GO
CREATE PROCEDURE dbo.GetPhotoFromDB
(
    @ProductPhotoID int,
    @CurrentDirectory nvarchar(1024),
    @FileName nvarchar(1024)
)
AS EXTERNAL NAME HandlingLOBUsingCLR.LargeObjectBinary.GetPhotoFromDB;
GO

Л. Использование выходного параметра-курсора

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

Сначала следует создать процедуру, объявляющую и открывающую курсор для таблицы Currency.

USE AdventureWorks;
GO
IF OBJECT_ID ( 'dbo.uspCurrencyCursor', 'P' ) IS NOT NULL
    DROP PROCEDURE dbo.uspCurrencyCursor;
GO
CREATE PROCEDURE dbo.uspCurrencyCursor 
    @CurrencyCursor CURSOR VARYING OUTPUT
AS
    SET NOCOUNT ON;
    SET @CurrencyCursor = CURSOR
    FORWARD_ONLY STATIC FOR
      SELECT CurrencyCode, Name
      FROM Sales.Currency;
    OPEN @CurrencyCursor;
GO

Затем выполним пакет, в котором объявляется локальная переменная-курсор, выполняется процедура, назначающая курсор локальной переменной, и выбираются строки из курсора.

USE AdventureWorks;
GO
DECLARE @MyCursor CURSOR;
EXEC dbo.uspCurrencyCursor @CurrencyCursor = @MyCursor OUTPUT;
WHILE (@@FETCH_STATUS = 0)
BEGIN;
     FETCH NEXT FROM @MyCursor;
END;
CLOSE @MyCursor;
DEALLOCATE @MyCursor;
GO

См. также

Задания

Справочник

Основные понятия

Другие ресурсы